Tuples, revert, keccak256

  • memory allows us to deal with data types that are larger than 32 bytes

  • if we want to return a struct or an array within one function, this would not be possible with a single variable, if that struct/array is larger than 32 bytes

  • we can do this in Yul by simply denoting the boundaries/area of memory whose values we wish to return (this is what Solidity does under the hood)

function return2and4() external pure returns (uint256, uint256) {
        assembly {
            mstore(0x00, 2)
            mstore(0x20, 4)
            return(0x00, 0x40) // beginning and end location in memory of items we want to return 
        }
    }
  • when we want to revert a statement, we also have to specify an area in memory to store the revert values, just like return

  • Solidity obscures the fact that in a revert case, data can still be sent so caller can debug it

  • Most of the time, we want to revert just so that execution stops, and not return a value. we can do this with: revert(0, 0)

  • values in abi.encode are stored in memory in solidity:

// Solidity example 

function hashV1() external pure returns (bytes32) {
        bytes memory toBeHashed = abi.encode(1, 2, 3);
        return keccak256(toBeHashed);
    }

// Yul equivalent version

function hashV2() external pure returns (bytes32) {
        assembly {
            let freeMemoryPointer := mload(0x40)

            // store 1, 2, 3 in memory
            mstore(freeMemoryPointer, 1)
            mstore(add(freeMemoryPointer, 0x20), 2)
            mstore(add(freeMemoryPointer, 0x40), 3)

            // update memory pointer to account for 3 32-byte variables 
            mstore(0x40, add(freeMemoryPointer, 0x60)) // increase memory pointer by 96 bytes

            mstore(0x00, keccak256(freeMemoryPointer, 0x60))
            return(0x00, 0x60)
        }
    }
  • in Yul, keccak256 takes in the start location in memory of the variables to be hashed, and how many bytes of data (0x60 in this case)

Last updated