Skip to content

Commit

Permalink
Allow storage access in fallback only contracts (#6031)
Browse files Browse the repository at this point in the history
## Description

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.

We also change the code generation for the method selector to make
selection optional, such as for full passthrough proxies.


## Checklist

- [x] I have linked to any relevant issues.
- [x] I have commented my code, particularly in hard-to-understand
areas.
- [x] I have updated the documentation where relevant (API docs, the
reference, and the Sway book).
- [x] If my change requires substantial documentation changes, I have
[requested support from the DevRel
team](https://github.com/FuelLabs/devrel-requests/issues/new/choose)
- [x] I have added tests that prove my fix is effective or that my
feature works.
- [x] I have added (or requested a maintainer to add) the necessary
`Breaking*` or `New Feature` labels where relevant.
- [x] I have done my best to ensure that my PR adheres to [the Fuel Labs
Code Review
Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md).
- [x] I have requested a review from the relevant team or maintainers.

Co-authored-by: Joshua Batty <joshpbatty@gmail.com>
  • Loading branch information
IGI-111 and JoshuaBatty authored May 21, 2024
1 parent 10b7221 commit ea97c34
Show file tree
Hide file tree
Showing 18 changed files with 105 additions and 37 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 <contact@fuel.sh>"]
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 @@ -4,9 +4,9 @@ use array_of_structs_abi::{Id, TestContract, Wrapper};
use std::hash::*;

#[cfg(experimental_new_encoding = false)]
const CONTRACT_ID = 0x7fae96947a8cad59cc2a25239f9f80897955d4c1b10d31510681f15842b93265;
const CONTRACT_ID = 0x14ed3cd06c2947248f69d54bfa681fe40d26267be84df7e19e253622b7921bbe;
#[cfg(experimental_new_encoding = true)]
const CONTRACT_ID = 0xe47e8943692557f67104afff960cb54e2d6d74b24aeefd8c2efeccad4e093bc0;
const CONTRACT_ID = 0xa5c32c71e9e1ecb39b04182b4e8b0582d1685dea7accbee94dc3be867a68c93f;

fn main() -> u64 {
let addr = abi(TestContract, CONTRACT_ID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ use std::constants::DEFAULT_SUB_ID;
use test_fuel_coin_abi::*;

#[cfg(experimental_new_encoding = false)]
const FUEL_COIN_CONTRACT_ID = 0x9e84e7e3006c94d5e23545829dbc926f50f90c6809c6e599ecddbf9a119e8104;
const FUEL_COIN_CONTRACT_ID = 0x4c7b43ef5a097d7cfb87600a4234e33311eeeeb8081e5ea7bb6d9a1f8555c9c4;
#[cfg(experimental_new_encoding = true)]
const FUEL_COIN_CONTRACT_ID = 0x47844008800c6f17ae24a30425094d733ca7a767cf2a915c8d5f73e3ff8f952b;
const FUEL_COIN_CONTRACT_ID = 0x5ad3dfd3def1db21312d64d274ec34924fc62b8126be51b8000b0c20a953c27a;

#[cfg(experimental_new_encoding = false)]
const BALANCE_CONTRACT_ID = 0x3b8cb681056f61a41e138b8884d7e3bb9332fbd7a8e38e3e0b0ada766cabfa4e;
const BALANCE_CONTRACT_ID = 0x3120fdd1b99c0c611308aff43a99746cc2c661c69c22aa56331d5f3ce5534ee9;
#[cfg(experimental_new_encoding = true)]
const BALANCE_CONTRACT_ID = 0xd354c2c31bb641863d03eaf320488ae276386ce60ef2e561258efef617dab462;
const BALANCE_CONTRACT_ID = 0x2393ab4d437acea9f3e916ddd728218ac2dca45dcfabe3b2fe83926a4dc0e737;

fn main() -> bool {
let default_gas = 1_000_000_000_000;
Expand Down Expand Up @@ -65,4 +65,4 @@ fn main() -> bool {
assert(balance_test_contract_balance == 3);

true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ script;
use balance_test_abi::BalanceTest;

#[cfg(experimental_new_encoding = false)]
const CONTRACT_ID = 0x3b8cb681056f61a41e138b8884d7e3bb9332fbd7a8e38e3e0b0ada766cabfa4e;
const CONTRACT_ID = 0x3120fdd1b99c0c611308aff43a99746cc2c661c69c22aa56331d5f3ce5534ee9;
#[cfg(experimental_new_encoding = true)]
const CONTRACT_ID = 0xd354c2c31bb641863d03eaf320488ae276386ce60ef2e561258efef617dab462;
const CONTRACT_ID = 0x2393ab4d437acea9f3e916ddd728218ac2dca45dcfabe3b2fe83926a4dc0e737;

fn main() -> bool {
let balance_test_contract = abi(BalanceTest, CONTRACT_ID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ script;
use basic_storage_abi::{BasicStorage, Quad};

#[cfg(experimental_new_encoding = false)]
const CONTRACT_ID = 0x5c0aef0c1af7601aa6b9fa0fc9efff0e956dcb93f855788222e172e67e717072;
const CONTRACT_ID = 0x044ab65bcabeebb73c88d8625ce392224c613cb1dae21ebedaa36bf6db1f5f4e;
#[cfg(experimental_new_encoding = true)]
const CONTRACT_ID = 0x37cdef21aab78b40f27486172cd39a320539de08b625e22d877e2bed6b826250;
const CONTRACT_ID = 0x70ea1e451bfa81030215e245f8644aef00043b50c16da4c5ab91fd32ff89a9d1;

fn main() -> u64 {
let addr = abi(BasicStorage, CONTRACT_ID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ script;
use contract_with_type_aliases_abi::*;

#[cfg(experimental_new_encoding = false)]
const CONTRACT_ID = 0x9d76ecbf446c30ef659efd1157d67d156de02b1e6c2ac2f9c744125571efa229;
const CONTRACT_ID = 0x0cbeb6efe3104b460be769bdc4ea101ebf16ccc16f2d7b667ec3e1c7f5ce35b5;
#[cfg(experimental_new_encoding = true)]
const CONTRACT_ID = 0x4c4bd277507ce1d47cbe793a8db2255ed44da30acacedb5e6aa565f7417ad3c8;
const CONTRACT_ID = 0x9e03072a3f094ed4b5af0ca6e1c244bafe8ded847d2c04aab331a9236ae7166a;

fn main() {
let caller = abi(MyContract, CONTRACT_ID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ script;
use storage_enum_abi::*;

#[cfg(experimental_new_encoding = false)]
const CONTRACT_ID = 0x0436d54f976e2dee0d77c81abc0d32cc7be985d8e0c97eeba27acd1caffdcea1;
const CONTRACT_ID = 0x0d2d9546e833c166b64a340f5694fa01ca6bb53c3ec681d6c1ade1b9c0a2bf46;
#[cfg(experimental_new_encoding = true)]
const CONTRACT_ID = 0xb19179a1379ccc402a3913d5cbaffd13ce7599218b6010b54ffaf22bca68fcf1;
const CONTRACT_ID = 0x53d4ee67238f0fbbcd2cdf1eff3115da320f3e893c70925d0f05b8cac72dd987;

fn main() -> u64 {
let caller = abi(StorageEnum, CONTRACT_ID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ script;
use auth_testing_abi::AuthTesting;

#[cfg(experimental_new_encoding = false)]
const CONTRACT_ID = 0xd7ef57c654a7e52ee8b85f34c64fa2f8e1a250eceb446cfe9805b175a0a7680f;
const CONTRACT_ID = 0xc2eec20491b53aab7232cbd27c31d15417b4e9daf0b89c74cc242ef1295f681f;
#[cfg(experimental_new_encoding = true)]
const CONTRACT_ID = 0xe453d2444c24bc0972b7a9cd25bdaaacc501bc2cef9e0aa577fffb5984e068f5;
const CONTRACT_ID = 0xd0b3be215b9f4f9a49af510c8a4f0b1f43ba640a73c6b6ea8a68a37fe71a27af;

// should be false in the case of a script
fn main() -> bool {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use core::codec::*;
use context_testing_abi::*;

#[cfg(experimental_new_encoding = false)]
const CONTRACT_ID = 0xe83ed45906627117f00f60e47140c6100b4b69133389a2dafd35bc3282329385;
const CONTRACT_ID = 0xc2ec2a4a1b20475700e6793c7f20ad8082294894242b17cf08b5fd7c0d3968ad;
#[cfg(experimental_new_encoding = true)]
const CONTRACT_ID = 0xf94d4eb2fb56ff3a5b85d6b853a6ea874846b22d71005611b95ed9aefc65b160;
const CONTRACT_ID = 0xc3ad47dc59ab201f60a87428fbcecdde4f33b0b31eb3aee6670ea924c6fd82fa;

fn main() -> bool {
let gas: u64 = u64::max();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ script;
use nested_struct_args_abi::*;

#[cfg(experimental_new_encoding = false)]
const CONTRACT_ID = 0xc615be7b48402210cbec3bc1667ab5a8093d449d5d8d1fdcc26e6f18e7942ea9;
const CONTRACT_ID = 0x64390eb0cac08d41b6476ad57d711b88846ea35ac800d4fc3c95a551e4039432;
#[cfg(experimental_new_encoding = true)]
const CONTRACT_ID = 0x8341183f70e4b6a4750b2e5806c2146e4b78d6873fed172767718deb206e3d24;
const CONTRACT_ID = 0xf12a88781f67f3ce2cdb4994e3571a6b42176c9ce63e3fdeb0247b1f319a8d83;

fn main() -> bool {
let caller = abi(NestedStructArgs, CONTRACT_ID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use storage_access_abi::*;
use std::hash::*;

#[cfg(experimental_new_encoding = false)]
const CONTRACT_ID = 0x0a58692bee60559887f0ac181c8a3b14ffb7a3a66256eec3f08e3135bfbecac9;
const CONTRACT_ID = 0x88732a14508defea37a44d0b0ae9af5c776253215180a1c3288f8d504ebb84db;
#[cfg(experimental_new_encoding = true)]
const CONTRACT_ID = 0x8ae216e6df492a4a983c34c5871bbe84c6aafa70fa25f1d76b771d8c8a72a1d7;
const CONTRACT_ID = 0xdebe2a83a36d9201ec836181ee0e013d6279a1a96dd039f7f701940d83b728e9;

fn main() -> bool {
let caller = abi(StorageAccess, CONTRACT_ID);
Expand Down
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 ea97c34

Please sign in to comment.