Skip to content

test_tload_calls()

Documentation for tests/cancun/eip1153_tstore/test_tload_calls.py::test_tload_calls@ffe48572.

Generate fixtures for these test cases for Bogota with:

fill -v tests/cancun/eip1153_tstore/test_tload_calls.py::test_tload_calls --fork Bogota

Ported .json vectors.

(04_tloadAfterCallFiller.yml) Loading a slot after a call to another contract is 0.

(12_tloadDelegateCallFiller.yml) delegatecall reads transient storage in the context of the current address

Source code in tests/cancun/eip1153_tstore/test_tload_calls.py
@pytest.mark.ported_from(
    [
        "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/Cancun/stEIP1153-transientStorage/04_tloadAfterCallFiller.yml",
        "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/Cancun/stEIP1153-transientStorage/12_tloadDelegateCallFiller.yml",
    ],
    pr=["https://github.com/ethereum/execution-spec-tests/pull/440"],
)
@pytest.mark.valid_from("Cancun")
@pytest.mark.parametrize("call_type", [Op.CALL, Op.CALLCODE, Op.DELEGATECALL])
def test_tload_calls(
    state_test: StateTestFiller, pre: Alloc, call_type: Op
) -> None:
    """
    Ported .json vectors.

    (04_tloadAfterCallFiller.yml) Loading a slot after a call to another
    contract is 0.

    (12_tloadDelegateCallFiller.yml) delegatecall reads transient storage in
    the context of the current address
    """
    # Storage variables
    slot_a_tload_after_subcall_result = 0
    slot_a_subcall_result = 1
    slot_b_subcall_tload_result = 2
    slot_b_subcall_updated_tload_result = 3

    def make_call(call_type: Op, address: Address) -> Bytecode:
        if call_type == Op.DELEGATECALL or call_type == Op.STATICCALL:
            return call_type(Op.GAS(), address, 0, 32, 0, 0)
        else:
            return call_type(Op.GAS(), address, 0, 0, 32, 0, 0)

    address_call = pre.deploy_contract(
        balance=1_000_000_000_000_000_000,
        code=Op.JUMPDEST()
        + Op.SSTORE(slot_b_subcall_tload_result, Op.TLOAD(0))
        + Op.TSTORE(0, 20)
        + Op.SSTORE(slot_b_subcall_updated_tload_result, Op.TLOAD(0)),
        storage={
            slot_b_subcall_tload_result: 0xFF,
            slot_b_subcall_updated_tload_result: 0xFF,
        },
    )

    address_to = pre.deploy_contract(
        balance=1_000_000_000_000_000_000,
        code=Op.JUMPDEST()
        + Op.TSTORE(0, 10)
        + Op.SSTORE(slot_a_subcall_result, make_call(call_type, address_call))
        + Op.SSTORE(slot_a_tload_after_subcall_result, Op.TLOAD(0)),
        storage={
            slot_a_subcall_result: 0xFF,
            slot_a_tload_after_subcall_result: 0xFF,
        },
    )

    post = {
        address_to: Account(
            storage={
                # other calls don't change context, therefore tload updated in
                # this account
                slot_a_tload_after_subcall_result: 10
                if call_type == Op.CALL
                else 20,
                slot_a_subcall_result: 1,
                # since context unchanged the subcall works as if continued
                # execution
                slot_b_subcall_tload_result: 0 if call_type == Op.CALL else 10,
                slot_b_subcall_updated_tload_result: 0
                if call_type == Op.CALL
                else 20,
            }
        ),
        address_call: Account(
            storage={
                slot_b_subcall_tload_result: 0
                if call_type == Op.CALL
                else 0xFF,
                slot_b_subcall_updated_tload_result: 20
                if call_type == Op.CALL
                else 0xFF,
            }
        ),
    }

    tx = Transaction(sender=pre.fund_eoa(), to=address_to)

    state_test(pre=pre, post=post, tx=tx)

Parametrized Test Cases

This test generates 3 parametrized test cases across 5 forks.