0

I have to loop through an array that will contain <10 addresses. I've already optimized for gas costs as much as possible using native Solidity. But I realized this loop can be improved further with inline assembly. As I am completely new to assembly I'm interested to see what this code would look like.

pragma solidity 0.8.20;

contract Optimized {

    address[] private specialaccounts;

    struct Amounts {
        uint amount;
    }
    
    mapping (address => Amounts) accounts;

    function optimizedAddLoopNativeSolidity() public view returns (uint result) {
      unchecked {
        uint i; uint len = specialaccounts.length;
        for (; i<len;) {
            if (specialaccounts[i] != address(0)) {
                result += accounts[specialaccounts[i]].amount;
            }
            ++i;
        }
        return result;
      }
    }

    function sameAddLoopButAssembly() public view returns (uint result) {
        assembly ("memory-safe") {
            // code here
        }
    }


}

1 Answer 1

1

I've augmented your example to make the connections between the slots clearer

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

contract Optimized {

    address[10] public  specialaccounts; //slot 0 - 9

    struct Amounts {
        uint amount;
    }
    mapping (address => Amounts) accounts;  //slot 10

    constructor() {
        for (uint i; i<10;) {
            specialaccounts[i] = address(uint160(i + (1<<100)));
            Amounts memory a = Amounts(10 + i);
            accounts[specialaccounts[i]] = a;
            ++i;
        }        
    }

    function optimizedAddLoopNativeSolidity() public view returns (uint result) {
        uint i; 
        uint len = specialaccounts.length;
        unchecked {
            for (; i<len;) {
                if (specialaccounts[i] != address(0)) {
                    result += accounts[specialaccounts[i]].amount;
                }
                ++i;
            }
        }
    }

    function sameAddLoopButAssembly() public view returns (uint result) {
        assembly ("memory-safe") {
            for { let n := 0 } lt(n, 10) { n := add(n, 1) } { 
                let addr := sload(n)
                if gt(addr, 0) {
                    //get specialaccounts[n] 
                    mstore(0, addr)
                    //link to slot 10
                    mstore(32, 10) 
                    //get link from mapping
                    let hash := keccak256(0, 64)
                    // add result and value from accounts
                    result := add(result, sload(hash))
                }
            } 
        }
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.