Yield Witch v2 contest - JohnSmith's results

Fixed-rate borrowing and lending on Ethereum

General Information

Platform: Code4rena

Start Date: 14/07/2022

Pot Size: $25,000 USDC

Total HM: 2

Participants: 63

Period: 3 days

Judge: PierrickGT

Total Solo HM: 1

Id: 147

League: ETH

Yield

Findings Distribution

Researcher Performance

Rank: 51/63

Findings: 1

Award: $17.03

🌟 Selected for report: 0

πŸš€ Solo Findings: 0

1). Caching storage variables in memory to save gas

Problem

Anytime you are reading from storage more than once, it is cheaper in gas cost to cache the variable in memory: a SLOAD cost from 100 to 2100 gas, while MLOAD and MSTORE cost 3 gas.

Proof of Concept

Instances include: https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L231-L236 line.proportion is read two times

Mitigation

Assign storage value to memory variable and use this variable instead of loading from storage multipple times.

2). Comparisons with zero for unsigned integers

Problem

> 0 is less efficient than != 0 for unsigned integers.

!= 0 costs less gas compared to > 0 for unsigned integers in require statements with the optimizer enabled (6 gas)

While it may seem that > 0 is cheaper than !=, this is only true without the optimizer enabled and outside a require statement. If you enable the optimizer at 10k AND you’re in a require statement, this will save gas.

Proof of Concept

Instances include: https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L255 require(auction_.start > 0, "Vault not under auction");

https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L300 require(auction_.start > 0, "Vault not under auction");

https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L358 require(auction_.start > 0, "Vault not under auction");

https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L393 if (liquidatorCut > 0) {

https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L398 if (auctioneerCut > 0) {

https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L416 require(auction_.start > 0, "Vault not under auction");

Mitigation

Replace > 0 with != 0

3). Custom Errors

Problem

Custom errors from Solidity 0.8.4 are cheaper than revert strings (cheaper deployment cost and runtime cost when the revert condition is met) while providing the same amount of information, as explained here https://blog.soliditylang.org/2021/04/21/custom-errors/

Custom errors are defined using the error statement

Proof of Concept

Instances include: https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L84 https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L102-L108 https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L189 https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L200 https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L255-L256 https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L300 https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L313 https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L328 https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L358 https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L365 https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L395 https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L416 https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L437

Mitigation

Replace require statements with custom errors.

4). Comparison Operators

Problem

In the EVM, there is no opcode for >= or <=. When using greater than or equal, two operations are performed: > and ==. Using strict comparison operators hence saves gas

Proof of Concept

Instances include:

https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L105 initialOffer == 0 || initialOffer >= 0.01e18,

https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L108 require(proportion >= 0.01e18, "Proportion below 1%");

https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L256 require(cauldron.level(vaultId) >= 0, "Undercollateralized");

https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L313 require(liquidatorCut >= minInkOut, "Not enough bought");

https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L108 require(liquidatorCut >= minInkOut, "Not enough bought");

https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L108 auction_.art - artIn >= debt.min * (10**debt.dec),

Mitigation

Replace <= and >= with < and >. For example change require(liquidatorCut >= minInkOut, "Not enough bought"); to require(minInkOut < liquidatorCut, "Not enough bought");

5). x = x + y is cheaper than x += y

Problem

x += y costs more than x = x + y same as x -= y

Proof of Concept

Instances include:

https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L204 limits_.sum += auction_.ink;

https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L259 limits[auction_.ilkId][auction_.baseId].sum -= auction_.ink;

https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L430 limits_.sum -= auction_.ink;

https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L443-L444 auction_.ink -= inkOut.u128(); auction_.art -= artIn.u128();

https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L450 limits_.sum -= inkOut.u128();

https://github.com/code-423n4/2022-07-yield/blob/main/contracts/Witch.sol#L598 liquidatorCut -= auctioneerCut;

Mitigation

Replace x += y and x -= y with x = x + y and x = x - y.

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax Β© 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter