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: 53/147
Findings: 2
Award: $131.95
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 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.9582 DAI - $54.96
Some tokens do not implement the ERC20 standard properly but are still accepted by most code that accepts ERC20 tokens. example Tether (USDT)'s transfer() and transferFrom() functions do not return booleans as the specification requires, and instead have no return value. When these sorts of tokens are cast to IERC20, their function signatures do not match and therefore the calls made, revert.
Use OpenZeppelin's SafeERC20
safeTransfer()/safeTransferFrom() instead
2022-08-olympus/blob/main/src/policies/Governance.sol#L259
VOTES.transferFrom(msg.sender, address(this), userVotes);
2022-08-olympus/blob/main/src/policies/Governance.sol#L312
VOTES.transferFrom(address(this), msg.sender, userVotes);
_safeMint()
should be used rather than _mint()
wherever possible_mint()
is discouraged in favor of _safeMint()
which ensures that the recipient is either an EOA or implements IERC721Receiver
.
You should change from _mint
to _safeMint
in terms of security.
2022-08-olympus/blob/main/src/modules/VOTES.sol#L36
_mint(wallet_, amount_);
Deprecated in favor of safeIncreaseAllowance() and safeDecreaseAllowance(). If only setting the initial allowance to the value that means infinite, safeIncreaseAllowance() can be used instead
Use safeIncreaseAllowance()
and safeDecreaseAllowance()
instead of safeApprove
2022-08-olympus/blob/main/src/policies/BondCallback.sol#L57
ohm.safeApprove(address(MINTR), type(uint256).max);
2022-08-olympus/blob/main/src/policies/Operator.sol#L167
ohm.safeApprove(address(MINTR), type(uint256).max);
You don't need to use assembly. assembly
should be avoided as much as possible due to various risks
You can change as follows.
assembly{ id := chainid() } => uint256 id = block.chainid
, assembly { size := extcodesize() } => uint256 size = address().code.length
2022-08-olympus/blob/main/src/utils/KernelUtils.sol#L34
size := extcodesize(target_)
Non-library/interface files should use fixed compiler versions, not floating ones
Delete the floating keyword ^
.
2022-08-olympus/blob/main/src/interfaces/IBondCallback.sol#L2
pragma solidity >=0.8.0;
2022-08-olympus/blob/main/src/policies/interfaces/IHeart.sol#L2
pragma solidity >=0.8.0;
2022-08-olympus/blob/main/src/policies/interfaces/IOperator.sol#L2
pragma solidity >=0.8.0;
constant/immutable
variablesVariable names that consist of all capital letters should be reserved for constant/immutable
variables
Variables that are not constant/immutable should be declared in lower case
2022-08-olympus/blob/main/src/policies/BondCallback.sol#L29
OlympusTreasury public TRSRY;
2022-08-olympus/blob/main/src/policies/BondCallback.sol#L30
OlympusMinter public MINTR;
2022-08-olympus/blob/main/src/policies/Governance.sol#L56
OlympusInstructions public INSTR;
2022-08-olympus/blob/main/src/policies/Governance.sol#L57
OlympusVotes public VOTES;
2022-08-olympus/blob/main/src/policies/VoterRegistration.sol#L10
OlympusVotes public VOTES;
Code architecture, incentives, and error handling/reporting questions/issues should be resolved before deployment
Delete TODO keyword
2022-08-olympus/blob/main/src/policies/Operator.sol#L657
/// TODO determine if this should use the last price from the MA or recalculate the current price, ideally last price is ok since it should have been just updated and should include check against secondary?
2022-08-olympus/blob/main/src/policies/TreasuryCustodian.sol#L51
// TODO Currently allows anyone to revoke any approval EXCEPT activated policies.
2022-08-olympus/blob/main/src/policies/TreasuryCustodian.sol#L52
// TODO must reorg policy storage to be able to check for deactivated policies.
2022-08-olympus/blob/main/src/policies/TreasuryCustodian.sol#L56
// TODO Make sure policy_
is an actual policy and not a random address.
Consider adding a two-phase transfer, where the current owner nominates the next owner, and the next owner has to call accept*()
to become the new owner. This prevents passing the ownership to an account that is unable to use it.
Consider implementing a two step process where the admin nominates an account and the nominated account needs to call an acceptOwnership() function for the transfer of admin to fully succeed. This ensures the nominated EOA account is a valid and active account.
2022-08-olympus/blob/main/src/Kernel.sol#L253
admin = target_;
Use a solidity version of at least 0.8.4 to get bytes.concat() instead of abi.encodePacked (<bytes>, <bytes>) Use a solidity version of at least 0.8.12 to get string.concat() instead of abi.encodePacked (<str>, <str>) Use a solidity version of at least 0.8.13 to get the ability to use using for with a list of free functions
Use more recent version of solidity.
2022-08-olympus/blob/main/src/interfaces/IBondCallback.sol#L2
pragma solidity >=0.8.0;
2022-08-olympus/blob/main/src/policies/interfaces/IHeart.sol#L2
pragma solidity >=0.8.0;
2022-08-olympus/blob/main/src/policies/interfaces/IOperator.sol#L2
pragma solidity >=0.8.0;
🌟 Selected for report: pfapostol
Also found by: 0x040, 0x1f8b, 0x85102, 0xDjango, 0xNazgul, 0xNineDec, 0xSmartContract, 0xkatana, Amithuddar, Aymen0909, Bnke0x0, CertoraInc, Chandr, CodingNameKiki, Deivitto, Dionysus, Diraco, ElKu, Fitraldys, Funen, GalloDaSballo, Guardian, IllIllI, JC, JansenC, Jeiwan, LeoS, Metatron, Noah3o6, RaymondFam, ReyAdmirado, Rohan16, RoiEvenHaim, Rolezn, Ruhum, Saintcode_, Shishigami, Sm4rty, SooYa, StevenL, Tagir2003, The_GUILD, TomJ, Tomo, Waze, __141345__, ajtra, apostle0x01, aviggiano, bobirichman, brgltd, c3phas, cRat1st0s, carlitox477, cccz, ch0bu, chrisdior4, d3e4, delfin454000, djxploit, durianSausage, erictee, exolorkistis, fatherOfBlocks, gogo, grGred, hyh, ignacio, jag, karanctf, kris, ladboy233, lukris02, m_Rassska, martin, medikko, natzuu, ne0n, newfork01, oyc_109, peiw, rbserver, ret2basic, robee, rokinot, rvierdiiev, sikorico, simon135, tnevler, zishansami
76.987 DAI - $76.99
The attention to gas savings throughout the project is excellent. The use of custom-error and the using the latest version were so impressive.
There are 9 gas optimization tips identified. I would be happy to help you with your project.
Gas Saved | Instances | Total | |
---|---|---|---|
G-1 | 8 | 3 | 24 |
G-2 | ? | 6 | |
G-3 | 2 | 2 | 4 |
G-4 | ? | 3 | |
G-5 | ? | 12 | |
G-6 | 20 | 34 | 680 |
G-7 | 25 | 7 | 175 |
G-8 | 35 | 17 | 595 |
G-9 | 80 | 28 | 2240 |
Uninitialized variables are assigned with the type's default value. Explicitly initializing a variable with it's default value costs unnecessary gas. Not overwriting the default for stack variables saves 8 gas. Storage and memory variables have larger savings
Delete useless variable declarations to save gas.
2022-08-olympus/blob/main/src/Kernel.sol#L397
for (uint256 i = 0; i < reqLength; ) {
2022-08-olympus/blob/main/src/utils/KernelUtils.sol#L43
for (uint256 i = 0; i < 5; ) {
2022-08-olympus/blob/main/src/utils/KernelUtils.sol#L58
for (uint256 i = 0; i < 32; ) {
uint256
instead of bool
Booleans are more expensive than uint256 or any type that takes up a full word because each writes operation emits an extra SLOAD to first read the slot's contents, replace the bits taken up by the boolean, and then write back. This is the compiler's defense against contract upgrades and pointer aliasing, and it cannot be disabled.
You should change from bool to uint256 to save gas
2022-08-olympus/blob/main/src/Kernel.sol#L113
bool public isActive;
2022-08-olympus/blob/main/src/modules/PRICE.sol#L62
bool public initialized;
2022-08-olympus/blob/main/src/policies/Heart.sol#L33
bool public active;
2022-08-olympus/blob/main/src/policies/Operator.sol#L63
bool public initialized;
2022-08-olympus/blob/main/src/policies/Operator.sol#L66
bool public active;
2022-08-olympus/blob/main/src/policies/Operator.sol#L735
bool sideActive = RANGE.active(high_);
A division/multiplication by any number x
being a power of 2 can be calculated by shifting log2(x)
to the right/left.
While the DIV
opcode uses 5 gas, the SHR
opcode only uses 3 gas.
Furthermore, Solidity's division operation also includes division-by-0 prevention which is bypassed using shifting.
You should change multiplication and division by powers of two to bit shift.
2022-08-olympus/blob/main/src/policies/Operator.sol#L372
int8 scaleAdjustment = int8(ohmDecimals) - int8(reserveDecimals) + (priceDecimals / 2);
2022-08-olympus/blob/main/src/policies/Operator.sol#L427
int8 scaleAdjustment = int8(reserveDecimals) - int8(ohmDecimals) + (priceDecimals / 2);
Use a solidity version of at least 0.8.0 to get overflow protection without SafeMath Use a solidity version of at least 0.8.2 to get simple compiler automatic inlining Use a solidity version of at least 0.8.3 to get better struct packing and cheaper multiple storage reads Use a solidity version of at least 0.8.4 to get custom errors, which are cheaper at deployment than revert()/require() strings Use a solidity version of at least 0.8.10 to have external calls skip contract existence checks if the external call has a return value
You should consider with your team members whether you should choose the latest version. The latest version has its advantages, but also it has disadvantages, such as the possibility of unknown bugs.
2022-08-olympus/blob/main/src/interfaces/IBondCallback.sol#L2
pragma solidity >=0.8.0;
2022-08-olympus/blob/main/src/policies/interfaces/IHeart.sol#L2
pragma solidity >=0.8.0;
2022-08-olympus/blob/main/src/policies/interfaces/IOperator.sol#L2
pragma solidity >=0.8.0;
The code should be refactored such that they no longer exist, or the block should do something useful, such as emitting an event or reverting.
Empty blocks should be removed or emit something (The code should be refactored such that they no longer exist, or the block should do something useful, such as emitting an event or reverting.
2022-08-olympus/blob/main/src/Kernel.sol#L85
constructor(Kernel kernel*) KernelAdapter(kernel*) {}
2022-08-olympus/blob/main/src/Kernel.sol#L95
function KEYCODE() public pure virtual returns (Keycode) {}
2022-08-olympus/blob/main/src/Kernel.sol#L100
function VERSION() external pure virtual returns (uint8 major, uint8 minor) {}
2022-08-olympus/blob/main/src/Kernel.sol#L105
function INIT() external virtual onlyKernel {}
2022-08-olympus/blob/main/src/Kernel.sol#L115
constructor(Kernel kernel*) KernelAdapter(kernel*) {}
2022-08-olympus/blob/main/src/Kernel.sol#L143
function requestPermissions() external view virtual returns (Permissions[] memory requests) {}
2022-08-olympus/blob/main/src/modules/INSTR.sol#L20
constructor(Kernel kernel*) Module(kernel*) {}
2022-08-olympus/blob/main/src/modules/TRSRY.sol#L45
constructor(Kernel kernel*) Module(kernel*) {}
2022-08-olympus/blob/main/src/policies/Governance.sol#L59
constructor(Kernel kernel*) Policy(kernel*) {}
2022-08-olympus/blob/main/src/policies/PriceConfig.sol#L15
constructor(Kernel kernel*) Policy(kernel*) {}
2022-08-olympus/blob/main/src/policies/TreasuryCustodian.sol#L24
constructor(Kernel kernel*) Policy(kernel*) {}
2022-08-olympus/blob/main/src/policies/VoterRegistration.sol#L16
constructor(Kernel kernel*) Policy(kernel*) {}
See this issue
If a function modifier such as onlyOwner
is used, the function will revert if a normal user tries to pay the function. Marking the function as payable will lower the gas cost for legitimate callers because the compiler will not include checks for whether a payment was provided. The extra opcodes avoided are CALLVALUE(2),DUP1(3),ISZERO(3),PUSH2(3),JUMPI(10),PUSH1(3),DUP1(3),REVERT(0),JUMPDEST(1),POP(2), which costs an average of about 21 gas per call to the function, in addition to the extra deployment cost
Saves 2400 gas per instance in deploying contract.
Saves about 20 gas per instance if using assembly to execute the function.
You should add the keyword payable
to those functions.
2022-08-olympus/blob/main/src/Kernel.sol#L76
function changeKernel(Kernel newKernel_) external onlyKernel {
2022-08-olympus/blob/main/src/Kernel.sol#L105
function INIT() external virtual onlyKernel {}
2022-08-olympus/blob/main/src/Kernel.sol#L126
function setActiveStatus(bool activate_) external onlyKernel {
2022-08-olympus/blob/main/src/Kernel.sol#L235
function executeAction(Actions action*, address target*) external onlyExecutor {
2022-08-olympus/blob/main/src/Kernel.sol#L439
function grantRole(Role role*, address addr*) public onlyAdmin {
2022-08-olympus/blob/main/src/Kernel.sol#L451
function revokeRole(Role role*, address addr*) public onlyAdmin {
2022-08-olympus/blob/main/src/policies/BondCallback.sol#L86
onlyRole("callback_whitelist")
2022-08-olympus/blob/main/src/policies/BondCallback.sol#L152
function batchToTreasury(ERC20[] memory tokens_) external onlyRole("callback_admin") {
2022-08-olympus/blob/main/src/policies/BondCallback.sol#L190
function setOperator(Operator operator_) external onlyRole("callback_admin") {
2022-08-olympus/blob/main/src/policies/Heart.sol#L130
function resetBeat() external onlyRole("heart_admin") {
2022-08-olympus/blob/main/src/policies/Heart.sol#L135
function toggleBeat() external onlyRole("heart_admin") {
2022-08-olympus/blob/main/src/policies/Heart.sol#L142
onlyRole("heart_admin")
2022-08-olympus/blob/main/src/policies/Heart.sol#L150
function withdrawUnspentRewards(ERC20 token_) external onlyRole("heart_admin") {
2022-08-olympus/blob/main/src/policies/Operator.sol#L195
function operate() external override onlyWhileActive onlyRole("operator_operate") {
2022-08-olympus/blob/main/src/policies/Operator.sol#L276
) external override onlyWhileActive nonReentrant returns (uint256 amountOut) {
2022-08-olympus/blob/main/src/policies/Operator.sol#L349
onlyRole("operator_reporter")
2022-08-olympus/blob/main/src/policies/Operator.sol#L500
onlyRole("operator_policy")
2022-08-olympus/blob/main/src/policies/Operator.sol#L510
function setThresholdFactor(uint256 thresholdFactor_) external onlyRole("operator_policy") {
2022-08-olympus/blob/main/src/policies/Operator.sol#L516
function setCushionFactor(uint32 cushionFactor_) external onlyRole("operator_policy") {
2022-08-olympus/blob/main/src/policies/Operator.sol#L531
) external onlyRole("operator_policy") {
2022-08-olympus/blob/main/src/policies/Operator.sol#L548
function setReserveFactor(uint32 reserveFactor_) external onlyRole("operator_policy") {
2022-08-olympus/blob/main/src/policies/Operator.sol#L563
) external onlyRole("operator_policy") {
2022-08-olympus/blob/main/src/policies/Operator.sol#L588
onlyRole("operator_admin")
2022-08-olympus/blob/main/src/policies/Operator.sol#L598
function initialize() external onlyRole("operator_admin") {
2022-08-olympus/blob/main/src/policies/Operator.sol#L618
function regenerate(bool high_) external onlyRole("operator_admin") {
2022-08-olympus/blob/main/src/policies/Operator.sol#L624
function toggleActive() external onlyRole("operator_admin") {
2022-08-olympus/blob/main/src/policies/PriceConfig.sol#L47
onlyRole("price_admin")
2022-08-olympus/blob/main/src/policies/PriceConfig.sol#L60
onlyRole("price_admin")
2022-08-olympus/blob/main/src/policies/PriceConfig.sol#L71
onlyRole("price_admin")
2022-08-olympus/blob/main/src/policies/TreasuryCustodian.sol#L46
) external onlyRole("custodian") {
2022-08-olympus/blob/main/src/policies/TreasuryCustodian.sol#L75
) external onlyRole("custodian") {
2022-08-olympus/blob/main/src/policies/TreasuryCustodian.sol#L84
) external onlyRole("custodian") {
2022-08-olympus/blob/main/src/policies/VoterRegistration.sol#L45
function issueVotesTo(address wallet*, uint256 amount*) external onlyRole("voter_admin") {
2022-08-olympus/blob/main/src/policies/VoterRegistration.sol#L53
function revokeVotesFrom(address wallet*, uint256 amount*) external onlyRole("voter_admin") {
++i
instead of i++
You can get cheaper for loops (at least 25 gas, however, can be up to 80 gas under certain conditions), by rewriting The post-increment operation (i++) boils down to saving the original value of i, incrementing it and saving that to a temporary place in memory, and then returning the original value; only after that value is returned is the value of i actually updated (4 operations).On the other hand, in pre-increment doesn't need to store temporary(2 operations) so, the pre-increment operation uses fewer opcodes and is thus more gas efficient.
You should change from i++ to ++i.
2022-08-olympus/blob/main/src/policies/Operator.sol#L488
decimals++;
2022-08-olympus/blob/main/src/policies/Operator.sol#L670
_status.low.count++;
2022-08-olympus/blob/main/src/policies/Operator.sol#L675
_status.low.count--;
2022-08-olympus/blob/main/src/policies/Operator.sol#L686
_status.high.count++;
2022-08-olympus/blob/main/src/policies/Operator.sol#L691
_status.high.count--;
2022-08-olympus/blob/main/src/utils/KernelUtils.sol#L49
i++;
2022-08-olympus/blob/main/src/utils/KernelUtils.sol#L64
i++;
You can save about 35 gas per instance if you change from x+=y
to x=x+y
This works equally well for subtraction, multiplication and division.
You should change from x+=y
to x=x+y
.
2022-08-olympus/blob/main/src/modules/PRICE.sol#L136
_movingAverage += (currentPrice - earliestPrice) / numObs;
2022-08-olympus/blob/main/src/modules/PRICE.sol#L138
_movingAverage -= (earliestPrice - currentPrice) / numObs;
2022-08-olympus/blob/main/src/modules/PRICE.sol#L222
total += startObservations_[i];
2022-08-olympus/blob/main/src/modules/TRSRY.sol#L96
reserveDebt[token*][msg.sender] += amount*;
2022-08-olympus/blob/main/src/modules/TRSRY.sol#L97
totalDebt[token*] += amount*;
2022-08-olympus/blob/main/src/modules/TRSRY.sol#L115
reserveDebt[token_][msg.sender] -= received;
2022-08-olympus/blob/main/src/modules/TRSRY.sol#L116
totalDebt[token_] -= received;
2022-08-olympus/blob/main/src/modules/TRSRY.sol#L131
if (oldDebt < amount*) totalDebt[token*] += amount_ - oldDebt;
2022-08-olympus/blob/main/src/modules/TRSRY.sol#L132
else totalDebt[token*] -= oldDebt - amount*;
2022-08-olympus/blob/main/src/modules/VOTES.sol#L56
balanceOf[from*] -= amount*;
2022-08-olympus/blob/main/src/modules/VOTES.sol#L58
balanceOf[to*] += amount*;
2022-08-olympus/blob/main/src/policies/BondCallback.sol#L143
amountsPerMarket[id][0] += inputAmount_;
2022-08-olympus/blob/main/src/policies/BondCallback.sol#L144
amountsPerMarket[id][1] += outputAmount_;
2022-08-olympus/blob/main/src/policies/Governance.sol#L194
totalEndorsementsForProposal[proposalId_] -= previousEndorsement;
2022-08-olympus/blob/main/src/policies/Governance.sol#L198
totalEndorsementsForProposal[proposalId_] += userVotes;
2022-08-olympus/blob/main/src/policies/Governance.sol#L252
yesVotesForProposal[activeProposal.proposalId] += userVotes;
2022-08-olympus/blob/main/src/policies/Governance.sol#L254
noVotesForProposal[activeProposal.proposalId] += userVotes;
2022-08-olympus/blob/main/src/policies/Heart.sol#L103
lastBeat += frequency();
indexed
for uint, bool, and addressUsing the indexed keyword for value types such as uint, bool, and address saves gas costs, as seen in the example below. However, this is only the case for value types, whereas indexing bytes and strings are more expensive than their unindexed version.
If you add indexed
keyword, you can save gas at least 80 gas in emitting event. Please read this document.
Also indexed keyword has more merits.
It can be useful to have a way to monitor the contract's activity after it was deployed. One way to accomplish this is to look at all transactions of the contract, however that may be insufficient, as message calls between contracts are not recorded in the blockchain. Moreover, it shows only the input parameters, not the actual changes being made to the state. Also events could be used to trigger functions in the user interface.
Up to three indexed
can be used per event and should be added.
2022-08-olympus/blob/main/src/modules/INSTR.sol#L11
event InstructionsStored(uint256 instructionsId);
2022-08-olympus/blob/main/src/modules/PRICE.sol#L26
event NewObservation(uint256 timestamp_, uint256 price_, uint256 movingAverage_);
2022-08-olympus/blob/main/src/modules/PRICE.sol#L27
event MovingAverageDurationChanged(uint48 movingAverageDuration_);
2022-08-olympus/blob/main/src/modules/PRICE.sol#L28
event ObservationFrequencyChanged(uint48 observationFrequency_);
2022-08-olympus/blob/main/src/modules/RANGE.sol#L20
event WallUp(bool high_, uint256 timestamp_, uint256 capacity_);
2022-08-olympus/blob/main/src/modules/RANGE.sol#L21
event WallDown(bool high_, uint256 timestamp_, uint256 capacity_);
2022-08-olympus/blob/main/src/modules/RANGE.sol#L22
event CushionUp(bool high_, uint256 timestamp_, uint256 capacity_);
2022-08-olympus/blob/main/src/modules/RANGE.sol#L23
event CushionDown(bool high_, uint256 timestamp_);
2022-08-olympus/blob/main/src/modules/RANGE.sol#L24
event PricesChanged(
2022-08-olympus/blob/main/src/modules/RANGE.sol#L30
event SpreadsChanged(uint256 cushionSpread_, uint256 wallSpread_);
2022-08-olympus/blob/main/src/modules/RANGE.sol#L31
event ThresholdFactorChanged(uint256 thresholdFactor_);
2022-08-olympus/blob/main/src/modules/TRSRY.sol#L20
event ApprovedForWithdrawal(address indexed policy_, ERC20 indexed token_, uint256 amount_);
2022-08-olympus/blob/main/src/modules/TRSRY.sol#L27
event DebtIncurred(ERC20 indexed token_, address indexed policy_, uint256 amount_);
2022-08-olympus/blob/main/src/modules/TRSRY.sol#L28
event DebtRepaid(ERC20 indexed token_, address indexed policy_, uint256 amount_);
2022-08-olympus/blob/main/src/modules/TRSRY.sol#L29
event DebtSet(ERC20 indexed token_, address indexed policy_, uint256 amount_);
2022-08-olympus/blob/main/src/policies/Governance.sol#L86
event ProposalSubmitted(uint256 proposalId);
2022-08-olympus/blob/main/src/policies/Governance.sol#L87
event ProposalEndorsed(uint256 proposalId, address voter, uint256 amount);
2022-08-olympus/blob/main/src/policies/Governance.sol#L88
event ProposalActivated(uint256 proposalId, uint256 timestamp);
2022-08-olympus/blob/main/src/policies/Governance.sol#L89
event WalletVoted(uint256 proposalId, address voter, bool for_, uint256 userVotes);
2022-08-olympus/blob/main/src/policies/Governance.sol#L90
event ProposalExecuted(uint256 proposalId);
2022-08-olympus/blob/main/src/policies/Heart.sol#L28
event Beat(uint256 timestamp_);
2022-08-olympus/blob/main/src/policies/Heart.sol#L29
event RewardIssued(address to_, uint256 rewardAmount_);
2022-08-olympus/blob/main/src/policies/Heart.sol#L30
event RewardUpdated(ERC20 token_, uint256 rewardAmount_);
2022-08-olympus/blob/main/src/policies/Operator.sol#L45
event Swap(
2022-08-olympus/blob/main/src/policies/Operator.sol#L51
event CushionFactorChanged(uint32 cushionFactor_);
2022-08-olympus/blob/main/src/policies/Operator.sol#L52
event CushionParamsChanged(uint32 duration_, uint32 debtBuffer_, uint32 depositInterval_);
2022-08-olympus/blob/main/src/policies/Operator.sol#L53
event ReserveFactorChanged(uint32 reserveFactor_);
2022-08-olympus/blob/main/src/policies/Operator.sol#L54
event RegenParamsChanged(uint32 wait_, uint32 threshold_, uint32 observe_);