Alchemix contest - 0xf15ers'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: 55/62

Findings: 1

Award: $91.84

🌟 Selected for report: 0

🚀 Solo Findings: 0

1. Initialisation of default value can be omitted

./contracts-full/TransmuterBuffer.sol:534:        uint256 want = 0;
./contracts-full/TransmuterBuffer.sol:549:        uint256 exchangeDelta = 0;
./contracts-full/EthAssetManager.sol:566:        uint256 total = 0;
./contracts-full/AlchemistV2.sol:1458:        uint256 totalValue = 0;
./contracts-full/ThreePoolAssetManager.sol:771:        uint256 normalizedTotal   = 0;
./contracts-full/ThreePoolAssetManager.sol:901:        uint256 total = 0; 

2. Array length can be cached in iteration of loops

  • The array length is computed in each iteration which can be cached to save gas
# Before 
for (uint256 i = 0; i < _underlyingTokens.length; i++) {...}
# After
uint length = _underlyingTokens.length
for (uint256 i = 0; i < _ length; i++) {...}
./contracts-full/StakingPools.sol:188:    for (uint256 _poolId = 0; _poolId < _pools.length(); _poolId++) {
./contracts-full/StakingPools.sol:363:    for (uint256 _poolId = 0; _poolId < _pools.length(); _poolId++) {
./contracts-full/TransmuterBuffer.sol:172:        for (uint256 i = 0; i < _yieldTokens[underlyingToken].length; i++) {
./contracts-full/TransmuterBuffer.sol:186:        for (uint256 i = 0; i < tokens.length; i++) {
./contracts-full/TransmuterBuffer.sol:235:            for (uint256 i = 0; i < registeredUnderlyings.length; i++) {
./contracts-full/TransmuterBuffer.sol:242:        for (uint256 i = 0; i < registeredUnderlyings.length; i++) {
./contracts-full/TransmuterBuffer.sol:272:        for (uint256 i = 0; i < registeredUnderlyings.length; i++) {
./contracts-full/TransmuterBuffer.sol:382:        for (uint256 j = 0; j < registeredUnderlyings.length; j++) {
./contracts-full/TransmuterBuffer.sol:479:        for (uint256 j = 0; j < weighting.tokens.length; j++) {
./contracts-full/base/Multicall.sol:14:        for (uint256 i = 0; i < data.length; i++) {
./contracts-full/AlchemistV2.sol:990:        for (uint256 i = 0; i < depositedTokens.values.length; i++) {
./contracts-full/AlchemistV2.sol:1282:        for (uint256 i = 0; i < depositedTokens.values.length; i++) {
./contracts-full/AlchemistV2.sol:1355:        for (uint256 i = 0; i < depositedTokens.values.length; i++) {
./contracts-full/AlchemistV2.sol:1461:        for (uint256 i = 0; i < depositedTokens.values.length; i++) {
./contracts-full/AlchemistV2.sol:1524:        for (uint256 i = 0; i < depositedTokens.values.length; i++) {
./contracts-full/CrossChainCanonicalBase.sol:57:        for (uint256 i = 0; i < _bridgeTokens.length; i++){ 
./contracts-full/CrossChainCanonicalBase.sol:141:        for (uint i = 0; i < bridgeTokensArray.length; i++){  

3. Pre-increment is cheaper than post-increment notation

  • ++i is cheaper than `i++'
./contracts-full/StakingPools.sol:188:    for (uint256 _poolId = 0; _poolId < _pools.length(); _poolId++) {
./contracts-full/StakingPools.sol:363:    for (uint256 _poolId = 0; _poolId < _pools.length(); _poolId++) {
./contracts-full/TransmuterBuffer.sol:172:        for (uint256 i = 0; i < _yieldTokens[underlyingToken].length; i++) {
./contracts-full/TransmuterBuffer.sol:186:        for (uint256 i = 0; i < tokens.length; i++) {
./contracts-full/TransmuterBuffer.sol:235:            for (uint256 i = 0; i < registeredUnderlyings.length; i++) {
./contracts-full/TransmuterBuffer.sol:242:        for (uint256 i = 0; i < registeredUnderlyings.length; i++) {
./contracts-full/TransmuterBuffer.sol:272:        for (uint256 i = 0; i < registeredUnderlyings.length; i++) {
./contracts-full/TransmuterBuffer.sol:382:        for (uint256 j = 0; j < registeredUnderlyings.length; j++) {
./contracts-full/TransmuterBuffer.sol:387:        for (uint256 i = 0; i < numYTokens; i++) {
./contracts-full/TransmuterBuffer.sol:479:        for (uint256 j = 0; j < weighting.tokens.length; j++) {
./contracts-full/base/Multicall.sol:14:        for (uint256 i = 0; i < data.length; i++) {
./contracts-full/EthAssetManager.sol:214:        for (uint256 i = 0; i < NUM_META_COINS; i++) {
./contracts-full/EthAssetManager.sol:567:        for (uint256 i = 0; i < NUM_META_COINS; i++) {
./contracts-full/AlchemistV2.sol:990:        for (uint256 i = 0; i < depositedTokens.values.length; i++) {
./contracts-full/AlchemistV2.sol:1282:        for (uint256 i = 0; i < depositedTokens.values.length; i++) {
./contracts-full/AlchemistV2.sol:1355:        for (uint256 i = 0; i < depositedTokens.values.length; i++) {
./contracts-full/AlchemistV2.sol:1461:        for (uint256 i = 0; i < depositedTokens.values.length; i++) {
./contracts-full/AlchemistV2.sol:1524:        for (uint256 i = 0; i < depositedTokens.values.length; i++) {
./contracts-full/ThreePoolAssetManager.sol:250:        for (uint256 i = 0; i < NUM_STABLE_COINS; i++) {
./contracts-full/ThreePoolAssetManager.sol:254:        for (uint256 i = 0; i < NUM_META_COINS; i++) {
./contracts-full/ThreePoolAssetManager.sol:353:        for (uint256 i = 0; i < 256; i++) {
./contracts-full/ThreePoolAssetManager.sol:773:        for (uint256 i = 0; i < NUM_STABLE_COINS; i++) {
./contracts-full/ThreePoolAssetManager.sol:902:        for (uint256 i = 0; i < NUM_META_COINS; i++) {
./contracts-full/CrossChainCanonicalBase.sol:57:        for (uint256 i = 0; i < _bridgeTokens.length; i++){ 
./contracts-full/CrossChainCanonicalBase.sol:141:        for (uint i = 0; i < bridgeTokensArray.length; i++){ 

4. Use != 0 instead of > 0 for Unsigned Integer Comparison

  • comparisons with != 0 is cheaper than >0.
/contracts-full/TransmuterBuffer.sol:521:        if (wantShares > 0) {
./contracts-full/TransmuterBuffer.sol:544:        if (want > 0) {
./contracts-full/TransmuterBuffer.sol:556:        if (exchangeDelta > 0) {
./contracts-full/TransmuterV2.sol:342:    if (state.distributeAmount > 0) {
./contracts-full/TransmuterV2.sol:409:    if (state.unexchangedBalance > 0 && satisfiedTick >= cache.occupiedTick) {
./contracts-full/TransmuterV2.sol:417:    if (state.unexchangedBalance > 0) {
./contracts-full/TransmuterV2.sol:459:    bool previouslyActive = cache.unexchangedBalance > 0;
./contracts-full/TransmuterV2.sol:460:    bool currentlyActive = state.unexchangedBalance > 0;
./contracts-full/AutoleverageBase.sol:172:            if (excessCollateral > 0) {
./contracts-full/AutoleverageCurveFactoryethpool.sol:22:        if (msg.value > 0) {
./contracts-full/gALCX.sol:75:        if (balance > 0) {
./contracts-full/AutoleverageCurveMetapool.sol:15:        if (msg.value > 0) revert IllegalArgument("msg.value should be 0");
./contracts-full/AlchemistV2.sol:353:        _checkArgument(config.creditUnlockBlocks > 0);
./contracts-full/AlchemistV2.sol:466:        _checkArgument(blocks > 0);
./contracts-full/AlchemistV2.sol:678:        _checkArgument(amount > 0);
./contracts-full/AlchemistV2.sol:692:        _checkArgument(amount > 0);
./contracts-full/AlchemistV2.sol:707:        _checkArgument(amount > 0);
./contracts-full/AlchemistV2.sol:722:        _checkState((debt = _accounts[recipient].debt) > 0);
./contracts-full/AlchemistV2.sol:746:        _checkArgument(amount > 0);
./contracts-full/AlchemistV2.sol:764:        _checkState((debt = _accounts[recipient].debt) > 0);
./contracts-full/AlchemistV2.sol:810:        _checkArgument(shares > 0);
./contracts-full/AlchemistV2.sol:826:        _checkState((unrealizedDebt = _calculateUnrealizedDebt(msg.sender)) > 0);
./contracts-full/AlchemistV2.sol:846:        _checkState(amountUnderlyingTokens > 0);
./contracts-full/AlchemistV2.sol:1103:        _checkArgument(amount > 0);
./contracts-full/AlchemistV2.sol:1267:        if (unlockedCredit > 0) {
./contracts-full/AlchemistV2.sol:1531:            currentAccruedWeight += unlockedCredit /0.0s

5. public functions can be changed to external to save gas

In ThreePoolAssetManager.sol exchangeRate() can be changed to external to save gas.

function exchangeRate(ThreePoolAsset asset) public view returns (uint256) {
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