4

I often see inline assembly in Solidity contracts. I consider this a bad practice because of the poor readability, however this is my opinion only and there must be valid reasons to use it. There are no other means to reach the same results in pure Solidity code? and if not, doesn't this show a lack in the language design?

2 Answers 2

4

I think there're some points that we need to use assembly in the documents

1. smth that cannot be done by plain Solidity

https://solidity.readthedocs.io/en/v0.5.3/assembly.html#example

pragma solidity >=0.4.0 <0.6.0;

library GetCode {
    function at(address _addr) public view returns (bytes memory o_code) {
        assembly {
            // retrieve the size of the code, this needs assembly
            let size := extcodesize(_addr)
            // allocate output byte array - this could also be done without assembly
            // by using o_code = new bytes(size)
            o_code := mload(0x40)
            // new "memory end" including padding
            mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
            // store length in memory
            mstore(o_code, size)
            // actually retrieve the code, this needs assembly
            extcodecopy(_addr, add(o_code, 0x20), 0, size)
        }
    }
}

2. Optimize code to produce efficient code

pragma solidity >=0.4.16 <0.6.0;

library VectorSum {
    // This function is less efficient because the optimizer currently fails to
    // remove the bounds checks in array access.
    function sumSolidity(uint[] memory _data) public pure returns (uint o_sum) {
        for (uint i = 0; i < _data.length; ++i)
            o_sum += _data[i];
    }

    // We know that we only access the array in bounds, so we can avoid the check.
    // 0x20 needs to be added to an array because the first slot contains the
    // array length.
    function sumAsm(uint[] memory _data) public pure returns (uint o_sum) {
        for (uint i = 0; i < _data.length; ++i) {
            assembly {
                o_sum := add(o_sum, mload(add(add(_data, 0x20), mul(i, 0x20))))
            }
        }
    }

    // Same as above, but accomplish the entire code within inline assembly.
    function sumPureAsm(uint[] memory _data) public pure returns (uint o_sum) {
        assembly {
           // Load the length (first 32 bytes)
           let len := mload(_data)

           // Skip over the length field.
           //
           // Keep temporary variable so it can be incremented in place.
           //
           // NOTE: incrementing _data would result in an unusable
           //       _data variable after this assembly block
           let data := add(_data, 0x20)

           // Iterate until the bound is not met.
           for
               { let end := add(data, mul(len, 0x20)) }
               lt(data, end)
               { data := add(data, 0x20) }
           {
               o_sum := add(o_sum, mload(data))
           }
        }
    }
}

And due to it's low level then we only use then we need and confident to use it as warning from solidity document

Inline assembly is a way to access the Ethereum Virtual Machine at a low level. This bypasses several important safety features and checks of Solidity. You should only use it for tasks that need it, and only if you are confident with using it.

3
  • 3
    That's the point, the recent 0x vulnerability was caused by assembly code put there to optimize space. It seems to me that security is king and accessing to assembly code is error prone even for the top developers.
    – Davide C
    Commented Jul 15, 2019 at 22:20
  • For security critical applications assembly is not a good idea.
    – ferit
    Commented Jul 16, 2019 at 18:35
  • I assume all smart contracts are security critical applications.
    – Davide C
    Commented Jul 17, 2019 at 20:09
3

In mainstream languages such as C++ when one needs to do something not achievable via core language, he usually calls library function, either from standard or third-party library. This function may be implemented in assembly or in a high-level language different from the language the function is called from. Whoever calls the function usually don't care about what language the function is implemented in.

For Solidity the situation should not be different. If you need something not available in core language, try to find library for this.

When we talk about optimizations, starting from version 0.5.0 Solidity permanently disabled so called loose assembly that gives developer full control over generated byte code. What is left is so called functional-style assembly, that allows developer to include sophisticated opcodes such as CREATE2, but does not allow him to directly control stack or execution flow. Compilation output of functional style assembly is then processed by Solidity optimizer. Thus inline assembly in Solidity is not suitable for manual optimizations anymore.

2
  • mainstream languages are not good for smart contracts imho. This is why I think inline assembly is a poor choice.
    – Davide C
    Commented Jul 15, 2019 at 22:22
  • Sorry, but I don't get your point. How the former implies the letter? Commented Jul 16, 2019 at 19:14

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.