01 - ReturnBool

Goal: Return a boolean value (true or false) from the Yul assembly block.

ReturnBool.t.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.13;

import {Test, console} from "forge-std/Test.sol";
import {ReturnBool} from "../src/ReturnBool.sol";

contract ReturnBoolTest is Test {
    ReturnBool public c;

    function setUp() public {
        c = new ReturnBool();
    }

    function test_ReturnBool() public {
        bool r = c.main();
        assertEq(r, true);
    }
}

In Yul, to return data we must explicitly store the value in memory and use the return opcode with a pointer and size. Booleans in the EVM are represented as 32-byte values (1 for true, 0 for false). To return true, we store 1 in memory and return 32 bytes; for false, we store 0.

ReturnBool.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.13;

contract ReturnBool {
    function main() external pure {
        assembly {
            // Store boolean true (1) at memory position 0
            mstore(0, 1)
            // Return 32 bytes from memory position 0 (bool true)
            return(0, 32)
        }
    }
}

Explanation: We use the mstore opcode to write to memory, and then return(0, 32) to output 32 bytes starting at memory position 0. The value 1 will be interpreted as true by Ethereum tools (and 0 as false). Memory is byte-addressable, so writing at offset 0 is convenient for returning data, although not memory safe (it overwrites the "scratch space for hashing methods", read more here).

Why not use free memory pointer?

In this scenario we just overwrite the scratch space with a single byte, it will not overwritten important memory regions. In future levels we will use free memory pointer if the data is long.

Run test:

forge test --mp test/ReturnBool.t.sol -vvvv

Last updated