diff --git a/tests/functional/builtins/codegen/test_create_functions.py b/tests/functional/builtins/codegen/test_create_functions.py index e4bf78b680..77e96970a1 100644 --- a/tests/functional/builtins/codegen/test_create_functions.py +++ b/tests/functional/builtins/codegen/test_create_functions.py @@ -860,3 +860,85 @@ def deploy_from_calldata(s: Bytes[1024], arg: uint256, salt: bytes32) -> address assert HexBytes(res) == create2_address_of(deployer.address, salt, initcode) assert env.get_code(res) == runtime + + +# test raw_create with all combinations of value and revert_on_failure kwargs (including not present at all) +# additionally parametrize whether the constructor reverts or not +@pytest.mark.parametrize("constructor_reverts", [True, False]) +@pytest.mark.parametrize("use_value", [True, False]) +@pytest.mark.parametrize("revert_on_failure", [True, False, None]) +def test_raw_create_revert_value_kws( + get_contract, env, tx_failed, constructor_reverts, revert_on_failure, use_value +): + value = 1 + value_assert = f"assert msg.value == {value}" if use_value else "" + to_deploy_code = f""" +foo: public(uint256) + +@deploy +@payable +def __init__(constructor_reverts: bool): + assert not constructor_reverts + {value_assert} + """ + + out = compile_code(to_deploy_code, output_formats=["bytecode", "bytecode_runtime"]) + initcode = bytes.fromhex(out["bytecode"].removeprefix("0x")) + runtime = bytes.fromhex(out["bytecode_runtime"].removeprefix("0x")) + + value_kw = f", value={value}" if use_value else "" + revert_kw = f", revert_on_failure={revert_on_failure}" if revert_on_failure is not None else "" + deployer_code = f""" +@external +def deploy() -> address: + return raw_create({initcode},{constructor_reverts}{revert_kw}{value_kw}) + """ + + deployer = get_contract(deployer_code) + env.set_balance(deployer.address, value) + + expect_revert = constructor_reverts and revert_on_failure in (True, None) + + if expect_revert: + with tx_failed(): + deployer.deploy() + else: + res = deployer.deploy() + if constructor_reverts: + assert res == ZERO_ADDRESS + assert env.get_code(res) == b"" + else: + assert env.get_code(res) == runtime + + +# test that raw_create correctly interfaces with the abi encoder +# and can handle dynamic arguments +def test_raw_create_dynamic_arg(get_contract, env): + array = [1, 2, 3] + + to_deploy_code = """ +foo: public(uint256) + +@deploy +@payable +def __init__(a: DynArray[uint256, 10]): + for i: uint256 in range(1, 4): + assert a[i - 1] == i + """ + + out = compile_code(to_deploy_code, output_formats=["bytecode", "bytecode_runtime"]) + initcode = bytes.fromhex(out["bytecode"].removeprefix("0x")) + runtime = bytes.fromhex(out["bytecode_runtime"].removeprefix("0x")) + + deployer_code = f""" +@external +def deploy() -> address: + a: DynArray[uint256, 10] = {array} + return raw_create({initcode}, a) + """ + + deployer = get_contract(deployer_code) + + res = deployer.deploy() + + assert env.get_code(res) == runtime