Platform: Code4rena
Start Date: 05/05/2022
Pot Size: $125,000 DAI
Total HM: 17
Participants: 62
Period: 14 days
Judge: leastwood
Total Solo HM: 15
Id: 120
League: ETH
Rank: 20/62
Findings: 2
Award: $379.61
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: IllIllI
Also found by: 0x1f8b, 0x4non, 0xDjango, 0xNazgul, 0xkatana, 0xsomeone, AuditsAreUS, BouSalman, BowTiedWardens, Cityscape, Funen, GimelSec, Hawkeye, JC, MaratCerby, MiloTruck, Picodes, Ruhum, TerrierLover, WatchPug, Waze, bobirichman, catchup, cccz, cryptphi, csanuragjain, delfin454000, ellahi, fatherOfBlocks, hake, horsefacts, hyh, jayjonah8, joestakey, kebabsec, kenta, mics, oyc_109, robee, samruna, shenwilly, sikorico, simon135, throttle, tintin
178.3839 DAI - $178.38
The _setupRole function is deprecated according to the Open Zeppelin comment
Deprecated. This function has issues similar to the ones found in {IERC20-approve}, and its usage is discouraged.
There are many safeApprove instances in code https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/EthAssetManager.sol#L576 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/EthAssetManager.sol#L577 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/EthAssetManager.sol#L620 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/EthAssetManager.sol#L621 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/EthAssetManager.sol#L671 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/EthAssetManager.sol#L672 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L382 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L383 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L478 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L479 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L782 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L783 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L838 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L839 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L879 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L880 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L908 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L909 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L944 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L945 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L987 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L988 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L236 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L238 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L243 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L245 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L284
This Open Zeppelin comment indicates it is deprecated https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol#L39-L43
Replace safeApprove with {safeIncreaseAllowance} or {safeDecreaseAllowance} instead
_setupRole
function usedThe _setupRole function is deprecated according to the Open Zeppelin comment
NOTE: This function is deprecated in favor of {_grantRole}
Use the recommended _grantRole function instead.
The _setupRole function, which is deprecated, is found in many places https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterV2.sol#L149 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2Base.sol#L63 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2Base.sol#L64 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2Base.sol#L142 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L85 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV1.sol#L43 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV1.sol#L44 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV1.sol#L102 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2.sol#L56 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2.sol#L57
This Open Zeppelin comment indicates it is deprecated https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/AccessControl.sol#L195
Replace the _setupRole function with _grantRole from the same Open Zeppelin library
🌟 Selected for report: IllIllI
Also found by: 0v3rf10w, 0x1f8b, 0x4non, 0xDjango, 0xNazgul, 0xf15ers, 0xkatana, 0xsomeone, AlleyCat, BowTiedWardens, Cityscape, Fitraldys, Funen, GimelSec, Hawkeye, JC, MaratCerby, MiloTruck, Randyyy, TerrierLover, Tomio, UnusualTurtle, WatchPug, Waze, _Adam, augustg, bobirichman, catchup, csanuragjain, ellahi, fatherOfBlocks, hake, hansfriese, horsefacts, ignacio, joestakey, kenta, mics, oyc_109, robee, samruna, sashik_eth, sikorico, simon135, throttle
201.2269 DAI - $201.23
Strings in solidity are handled in 32 byte chunks. A require string longer than 32 bytes uses more gas. Shortening these strings will save gas.
https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/StakingPools.sol#L106 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/StakingPools.sol#L124 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/StakingPools.sol#L131 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/StakingPools.sol#L160 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/StakingPools.sol#L183
Shorten all require strings to less than 32 characters
Using > 0
uses slightly more gas than using != 0
. Use != 0
when comparing uint variables to zero, which cannot hold values below zero
Locations where this was found include https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/gALCX.sol#L75 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterV2.sol#L342 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterV2.sol#L409 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterV2.sol#L417 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterV2.sol#L459 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterV2.sol#L460 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AutoleverageCurveFactoryethpool.sol#L22 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L353 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L466 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L678 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L692 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L707 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L722 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L746 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L764 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L810 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L826 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L846 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L1103 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L1267 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L1531 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AutoleverageBase.sol#L172 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AutoleverageCurveMetapool.sol#L15 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L521 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L544 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L556
Replace > 0
with != 0
to save gas
Solidity does not recognize null as a value, so uint variables are initialized to zero. Setting a uint variable to zero is redundant and can waste gas.
There are many places where an int is initialized to zero https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/EthAssetManager.sol#L214 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/EthAssetManager.sol#L566 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/EthAssetManager.sol#L567 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/StakingPools.sol#L188 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/StakingPools.sol#L363 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/adapters/fuse/FuseTokenAdapterV1.sol#L36 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L990 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L1282 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L1355 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L1458 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L1461 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L1524 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/test/TransmuterBufferMock.sol#L15 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/test/yearn/YearnVaultMock.sol#L19 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/test/yearn/YearnVaultMock.sol#L58 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/test/TestYieldToken.sol#L67 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/base/Multicall.sol#L14 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L250 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L254 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L353 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L771 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L773 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L901 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L902 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L172 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L186 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L235 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L242 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L272 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L382 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L387 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L479 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L534 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L549 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/CrossChainCanonicalBase.sol#L57 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/CrossChainCanonicalBase.sol#L141
Remove the redundant zero initialization
uint256 i;
instead of uint256 i = 0;
Using a prefix increment (++i) instead of a postfix increment (i++) saves gas for each loop cycle and so can have a big gas impact when the loop executes on a large number of elements.
There are many examples of this in for loops https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/EthAssetManager.sol#L214 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/EthAssetManager.sol#L567 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/StakingPools.sol#L188 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/StakingPools.sol#L363 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L990 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L1282 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L1355 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L1461 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L1524 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L250 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L254 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L353 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L773 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L902 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L172 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L186 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L235 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L242 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L272 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L382 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L387 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L479 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/CrossChainCanonicalBase.sol#L57 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/CrossChainCanonicalBase.sol#L141
Use prefix not postfix to increment in a loop
For loops that use i++ do not need to use safemath for this operation because the loop would run out of gas long before this point. Making this addition operation unsafe using unchecked saves gas.
Sample code to make the for loop increment unsafe
for (uint i = 0; i < length; i = unchecked_inc(i)) { // do something that doesn't change the value of i } function unchecked_inc(uint i) returns (uint) { unchecked { return i + 1; } }
Idea borrowed from https://gist.github.com/hrkrshnn/ee8fabd532058307229d65dcd5836ddc#the-increment-in-for-loop-post-condition-can-be-made-unchecked
There are many for loops and that can use this change https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/EthAssetManager.sol#L214 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/EthAssetManager.sol#L567 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/StakingPools.sol#L188 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/StakingPools.sol#L363 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L990 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L1282 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L1355 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L1461 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L1524 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/test/TransmuterBufferMock.sol#L15 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/base/Multicall.sol#L14 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L250 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L254 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L353 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L773 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L902 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L172 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L186 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L235 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L242 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L272 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L382 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L387 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L479 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/CrossChainCanonicalBase.sol#L57
Make the increment in for loops unsafe to save gas
Caching the array length outside a loop saves reading it on each iteration, as long as the array's length is not changed during the loop. This saves gas.
This optimization is already used in some places, but is not used in this place https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/StakingPools.sol#L188 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/StakingPools.sol#L363 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L990 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L1282 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L1355 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L1461 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L1524 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/test/TransmuterBufferMock.sol#L15 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/base/Multicall.sol#L14 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L172 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L186 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L235 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L242 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L272 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L382 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L479
Cache the array length before the for loop
Many constant variables are public, but changing the visibility of this variable to private or internal can save gas.
https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/gALCX.sol#L15 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterV2.sol#L96 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterV2.sol#L99 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterV2.sol#L102 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterV2.sol#L105 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/WETHGateway.sol#L14 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AutoleverageCurveFactoryethpool.sol#L14 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L46 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L51 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemistV2.sol#L54 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2Base.sol#L22 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2Base.sol#L25 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2Base.sol#L28 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2Base.sol#L31 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L31 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L34 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L37 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV1.sol#L22 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV1.sol#L25 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2.sol#L21 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2.sol#L24 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2.sol#L27 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2.sol#L30
Declare some public variables as private or internal to save gas
When multiply or dividing by a power of two, it is cheaper to bitshift than to use standard math operations.
There is a divide by 2 operation on this line https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L355
Bitshift right by one bit instead of dividing by 2 to save gas
Identifying a function as payable saves gas. Functions that have the onlyOwner modifier cannot be called by normal users and will not mistakenly receive ETH. These functions can be payable to save gas. This is especially relevant because withdrawAll functions exist to withdraw any ETH accidentally sent.
There are many functions that have the onlyOwner modifier in the contracts. Some examples are https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/gALCX.sol#L39 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/gALCX.sol#L46 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/WETHGateway.sol#L35 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/CrossChainCanonicalBase.sol#L133 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/CrossChainCanonicalBase.sol#L139 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/CrossChainCanonicalBase.sol#L156 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/CrossChainCanonicalBase.sol#L163 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/CrossChainCanonicalBase.sol#L169 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/CrossChainCanonicalBase.sol#L173
Add payable to these functions for gas savings
_setupRole
call with _grantRole
The _setupRole function calls _grantRole, so it would save gas to call _grantRole directly to remove the function call
The _setupRole function, which is deprecated, is found in many places https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2Base.sol#L63 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2Base.sol#L64 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2Base.sol#L142 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L85 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV1.sol#L43 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV1.sol#L44 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV1.sol#L102 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2.sol#L56 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2.sol#L57 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2.sol#L129
This Open Zeppelin _setupRole code shows it is deprecated and only calls _grantRole https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/AccessControl.sol#L197-L199
Replace the _setupRole function with _grantRole from the same Open Zeppelin library
Solidity 0.8.11 is used in Alchemix. The latest release of solidity includes changes that can provide gas savings. Solidity version 0.8.13 can save more gas with Yul IR pipeline https://blog.soliditylang.org/2022/03/16/solidity-0.8.13-release-announcement/#yul-ir-pipeline-production-ready
Use solidity release 0.8.13 with Yul IR pipeline for gas savings
Solidity errors introduced in version 0.8.4 can save gas on revert conditions https://blog.soliditylang.org/2021/04/21/custom-errors/ https://twitter.com/PatrickAlphaC/status/1505197417884528640
Many require blocks are used in the code which can be replaced with errors to save gas https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/gALCX.sol#L33 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/gALCX.sol#L90 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/gALCX.sol#L107 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/StakingPools.sol#L106 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/StakingPools.sol#L114 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/StakingPools.sol#L124 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/StakingPools.sol#L131 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/StakingPools.sol#L160 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/StakingPools.sol#L183 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV1.sol#L51 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV1.sol#L57 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV1.sol#L63 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV1.sol#L77 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV1.sol#L78 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV1.sol#L81
Replace require blocks with new solidity errors described in https://blog.soliditylang.org/2021/04/21/custom-errors/
The comparison operators >= and <= use more gas than >, <, or ==. Replacing the >= and ≤ operators with a comparison operator that has an opcode in the EVM saves gas
The existing code is https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L161
credit = debt >= 0 ? 0 : SafeCast.toUint256(-debt);
A simple comparison can be used for gas savings by reversing the logic
credit = debt < 0 ? SafeCast.toUint256(-debt) : 0;
Replace the comparison operator and reverse the logic to save gas using the suggestions above
Using calldata instead of memory for function arguments saves gas sometimes. This can happen when a function is called externally and the memory array values are kept in calldata
and copied to memory
during ABI decoding (using the opcode calldataload
and mstore
). If the array is used in a for loop, arr[i]
accesses the value in memory using a mload
. If calldata is used instead, then instead of going via memory, the value is directly read from calldata
using calldataload
. That is, there are no intermediate memory operations that carries this value.
At least one case of function arguments using memory instead of calldata can use this to save gas https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/CrossChainCanonicalBase.sol#L46 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/CrossChainCanonicalAlchemicTokenV2.sol#L11
Change function arguments from memory to calldata
Use unchecked when there is no overflow risk to save gas. Before index is decreased in remove it is checked for zero condition. This means index will not underflow and can be unchecked.
Index is decreased on line 42
https://github.com/code-423n4/2022-05-alchemix/blob/main/contracts-full/libraries/Sets.sol#L42
index--
But line 37 handles the case when index is zero, do index will not underflow https://github.com/code-423n4/2022-05-alchemix/blob/main/contracts-full/libraries/Sets.sol#L42
The entire line can be unchecked because the subtraction only happens when it cannot overflow
The same logic can be used in line 44, because if self.indexes[value] is not zero, then self.values has a length greater than zero
https://github.com/code-423n4/2022-05-alchemix/blob/main/contracts-full/libraries/Sets.sol#L44
uint256 lastIndex = self.values.length - 1;
Add unchecked around math that can't overflow for gas savings
unchecked { index--; }
and unchecked { uint256 lastIndex = self.values.length - 1; }
Using internal functions instead of modifier saves gas. Some contracts use this but not all contracts.
Modifiers exist in many places https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/gALCX.sol#L32 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/EthAssetManager.sol#L185 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/EthAssetManager.sol#L193 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterV2.sol#L167 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterV2.sol#L175 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterV2.sol#L183 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterConduit.sol#L27 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/StakingPools.sol#L113 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/base/Mutex.sol#L16 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L220 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/ThreePoolAssetManager.sol#L228 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2Base.sol#L70 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2Base.sol#L78 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2Base.sol#L86 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L96 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L106 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L114 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/TransmuterBuffer.sol#L122 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV1.sol#L50 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV1.sol#L56 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV1.sol#L62 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/CrossChainCanonicalBase.sol#L33 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2.sol#L64 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2.sol#L72 https://github.com/code-423n4/2022-05-alchemix/tree/main/contracts-full/AlchemicTokenV2.sol#L80
Replace the modifier in AlchemistTokenV2 with internal functions. This is done properly in AlchemistV2