13

This trivial contract:

contract Test {
    function test() returns (string) {
        return "foobar";
    }
}

Results in assembly code output (in the solidity web compiler) for the function 'test' that looks like this:

   tag 2            function test() returns (strin...
      JUMPDEST          function test() returns (strin...
      PUSH 0            contract Test {\n    function ...
      PUSH 60           contract Test {\n    function ...
      MSTORE            string
      PUSH C0           return "foobar"
      PUSH 40           contract Test {\n    function ...
      MSTORE            return "foobar"
      PUSH 6            return "foobar"
      PUSH 80           string
      SWAP1             return "foobar"
      DUP2          return "foobar"
      MSTORE            return "foobar"
      PUSH 666F6F6261720000000000000000000000000000000000000000000000000000         return "foobar"
      PUSH A0           return "foobar"
      MSTORE            return "foobar"
      PUSH 20           string
      PUSH C0           return "foobar"
      SWAP1             function test() returns (strin...
      DUP2          function test() returns (strin...
      MSTORE            function test() returns (strin...
      PUSH 6            return "foobar"
      PUSH E0           function test() returns (strin...
      DUP2          function test() returns (strin...
      SWAP1             function test() returns (strin...
      MSTORE            function test() returns (strin...
      DUP2          return "foobar"
      SWAP1             return "foobar"
      PUSH 100          function test() returns (strin...
      SWAP1             function test() returns (strin...
      PUSH A0           return "foobar"
      SWAP1             return "foobar"
      DUP1          return "foobar"
      DUP4          function test() returns (strin...
      DUP2          return "foobar"
      DUP5          return "foobar"
      PUSH 0            contract Test {\n    function ...
      PUSH 4            function test() returns (strin...
      PUSH 12           function test() returns (strin...
      CALL          function test() returns (strin...
      POP           
      POP           
      DUP2          function test() returns (strin...
      MLOAD             function test() returns (strin...
      PUSH FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF         
      NOT           
      AND           function test() returns (strin...
      SWAP1             function test() returns (strin...
      SWAP2             function test() returns (strin...
      MSTORE            function test() returns (strin...
      POP           
      POP           
      PUSH 40           contract Test {\n    function ...
      MLOAD             function test() returns (strin...
      PUSH 120          function test() returns (strin...
      DUP2          function test() returns (strin...
      SWAP1             function test() returns (strin...
      SUB           function test() returns (strin...
      SWAP3             function test() returns (strin...
      POP           
      SWAP1             function test() returns (strin...
      POP           
      RETURN

I can see the hex version of the string, and its length, being written to memory fairly early on. Then it does a whole lot of weird stuff, and issues a CALL with very little gas to address '4', as far as I can tell. The Ethereum yellowpaper says that the contract at address 4 implements the identity function, which seems an entirely pointless thing to call in this context.

Why is it doing this for what looks like a very straightforward 'return'?

10

On discussing with the Solidity devs on Gitter, this is made clear: Solidity uses the identity function as a cheap memcpy operation, and the optimizer isn't currently clever enough to realise that it can just load the string literal into memory as the entirety of the return value. So, it loads the string into memory, uses the identity function to memcpy it to the return location, and then returns it.

0

The assembly code includes all functions required to create the contract of which identification is one, i.e the contract has to be identifiable. The actual 'test' function does not use all the functions in the assembly code.

  • The identity contract is not for identifying things; it's a contract that implements the identity function - it literally produces the same output as its input. And yes, it does form part of the executed bytecode; I removed the (small) deployment header/constructor from the generated assembly. – Nick Johnson Apr 19 '16 at 6:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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