Alchemix contest - 0xkatana's results

A protocol for self-repaying loans with no liquidation risk.

General Information

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

Alchemix

Findings Distribution

Researcher Performance

Rank: 20/62

Findings: 2

Award: $379.61

🌟 Selected for report: 0

🚀 Solo Findings: 0

[L-01] safeApprove is deprecated

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

[L-02] Deprecated _setupRole function used

The _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

[G-01] Short require strings save gas

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

[G-02] Use != 0 instead of > 0

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

[G-03] Redundant zero initialization

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;

[G-04] Use prefix not postfix in loops

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

[G-05] For loop incrementing can be unsafe

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

[G-06] Cache array length before loop

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

[G-07] Non-public variables save gas

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

[G-08] Bitshift for divide by 2

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

[G-09] Add payable to functions that won't receive ETH

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

[G-10] Replace _setupRole call with _grantRole

Impact

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

[G-11] Use newer solidity version

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

[G-12] Use Solidity errors instead of require

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/

[G-13] Use simple comparison in trinary logic

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

[G-14] Use calldata instead of memory for function arguments

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

Source https://gist.github.com/hrkrshnn/ee8fabd532058307229d65dcd5836ddc#use-calldata-instead-of-memory-for-function-parameters

Change function arguments from memory to calldata

[G-15] Save gas with unchecked

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; }

[G-16] Use internal function not modifier

Using internal functions instead of modifier saves gas. Some contracts use this but not all contracts.

Source https://blog.polymath.network/solidity-tips-and-tricks-to-save-gas-and-reduce-bytecode-size-c44580b218e6#dde7

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

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