-
Notifications
You must be signed in to change notification settings - Fork 463
Open
Labels
C-bugSomething isn't workingSomething isn't working
Description
As per our docs:
An ink! message with a
&self
receiver may only read state whereas an ink! message with a&mut self
receiver may mutate the contract's storage.
However this isn't enforced: Via the Environment
, supposedly immutable contracts can change the state in many ways. Things that are currently possible in immutable contracts that should fail to compile:
- writing to storage
- emitting events
- calling chain extensions
call_runtime
- instantiating contracts
- calling contracts
- terminate
- transfer value
Minimal reproducer
While direct storage writes are enforced by the &self
receiver, this can easily be circumvented.
#![cfg_attr(not(feature = "std"), no_std, no_main)]
#[ink::contract]
mod mutable {
use ink::storage::traits::ManualKey;
use ink::storage::Lazy;
/// A contract for testing `Mapping` functionality.
#[ink(storage)]
#[derive(Default)]
pub struct Mutable {}
impl Mutable {
#[ink(constructor)]
pub fn new() -> Self {
Self {}
}
/// This function manipulates state despite receiving `&self`
#[ink(message)]
pub fn read_only(&self, a: u8) {
ink::env::set_contract_storage(&a, &a);
// The same just with an added layer of inderiction
Lazy::<u8, ManualKey<127>>::new().set(&127);
}
#[ink(message)]
pub fn get(&self, a: u8) -> (Option<u8>, Option<u8>) {
(
ink::env::get_contract_storage(&a).unwrap(),
ink::env::get_contract_storage(&127).unwrap(),
)
}
}
}
Metadata
Metadata
Assignees
Labels
C-bugSomething isn't workingSomething isn't working