Skip to content

Commit

Permalink
Allow storage access in fallback only contracts
Browse files Browse the repository at this point in the history
Contract that do not implement any ABI (and therefore have no methods)
do not always properly set the storage annotations of the entry function
because the fallback function's storage annotations are not taken into
account. This changes makes sure that the storage function's storage
permissions are also considered.
  • Loading branch information
IGI-111 committed May 19, 2024
1 parent f9a72da commit f463e58
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 14 deletions.
32 changes: 20 additions & 12 deletions sway-core/src/semantic_analysis/ast_node/declaration/auto_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -628,27 +628,19 @@ where
let method_name = decl.name.as_str();

if args_types == "()" {
code.push_str(&format!("if method_name == \"{method_name}\" {{
code.push_str(&format!("if _method_name == \"{method_name}\" {{
let result_{method_name}: raw_slice = encode::<{return_type}>(__contract_entry_{method_name}());
__contract_ret(result_{method_name}.ptr(), result_{method_name}.len::<u8>());
}}\n"));
} else {
code.push_str(&format!("if method_name == \"{method_name}\" {{
code.push_str(&format!("if _method_name == \"{method_name}\" {{
let args: {args_types} = decode_second_param::<{args_types}>();
let result_{method_name}: raw_slice = encode::<{return_type}>(__contract_entry_{method_name}({expanded_args}));
__contract_ret(result_{method_name}.ptr(), result_{method_name}.len::<u8>());
}}\n"));
}
}

let att: String = match (reads, writes) {
(true, true) => "#[storage(read, write)]",
(true, false) => "#[storage(read)]",
(false, true) => "#[storage(write)]",
(false, false) => "",
}
.into();

let fallback = if let Some(fallback_fn) = fallback_fn {
let fallback_fn = engines.de().get(&fallback_fn);
let Some(return_type) = Self::generate_type(engines, fallback_fn.return_type.type_id)
Expand All @@ -659,16 +651,32 @@ where
return Err(err);
};
let method_name = fallback_fn.name.as_str();

match fallback_fn.purity {
Purity::Pure => {}
Purity::Reads => reads = true,
Purity::Writes => writes = true,
Purity::ReadsWrites => {
reads = true;
writes = true;
}
}
format!("let result: raw_slice = encode::<{return_type}>({method_name}()); __contract_ret(result.ptr(), result.len::<u8>());")
} else {
// as the old encoding does
format!("__revert({});", MISMATCHED_SELECTOR_REVERT_CODE)
};

let att: String = match (reads, writes) {
(true, true) => "#[storage(read, write)]",
(true, false) => "#[storage(read)]",
(false, true) => "#[storage(write)]",
(false, false) => "",
}
.into();

let code = format!(
"{att} pub fn __entry() {{
let method_name = decode_first_param::<str>();
let _method_name = decode_first_param::<str>();
{code}
{fallback}
}}"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[[package]]
name = "core"
source = "path+from-root-542D0E8F1D1E5950"

[[package]]
name = "fallback_only"
source = "member"
dependencies = [
"core",
"std",
]

[[package]]
name = "std"
source = "path+from-root-542D0E8F1D1E5950"
dependencies = ["core"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
license = "Apache-2.0"
name = "fallback_only"
implicit-std = false

[dependencies]
core = { path = "../../../../../../../sway-lib-core" }
std = { path = "../../../../../../../sway-lib-std" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"configurables": [],
"encoding": "1",
"functions": [],
"loggedTypes": [],
"messagesTypes": [],
"types": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"configurables": [],
"encoding": "1",
"functions": [],
"loggedTypes": [],
"messagesTypes": [],
"types": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
contract;

use std::execution::run_external;
use std::constants::ZERO_B256;

#[namespace(SRC1822)]
storage {
target: ContractId = ContractId::from(ZERO_B256),
}

#[fallback]
#[storage(read)]
fn fallback() {
run_external(storage.target.read())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
category = "compile"
validate_abi = true
expected_warnings = 0
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ fn test_foo() {

#[test(should_revert)]
fn test_fail() {
let contract_id = 0x535d1bbf19a6c7e5e2e2906d09b8c959bd211391e7a3c7602c5dab0455f78305;
let contract_id = 0xed94087f1dea86a4590624880f80e97522daedb48a2398a37f6aa039599715ef;
let caller = abi(MyContract, contract_id);
let result = caller.test_function {}();
assert(result == false)
}

#[test]
fn test_success() {
let contract_id = 0x535d1bbf19a6c7e5e2e2906d09b8c959bd211391e7a3c7602c5dab0455f78305;
let contract_id = 0xed94087f1dea86a4590624880f80e97522daedb48a2398a37f6aa039599715ef;
let caller = abi(MyContract, contract_id);
let result = caller.test_function {}();
assert(result == true)
Expand Down

0 comments on commit f463e58

Please sign in to comment.