Access Control
Smart contracts require the ability to restrict access to and identify certain users or contracts. Unlike account-based blockchains, transactions in UTXO-based blockchains (i.e. Fuel) do not necessarily have a unique transaction sender. Additional logic is needed to handle this difference, and is provided by the standard library.
msg_sender
To deliver an experience akin to the EVM's access control, the std
library provides a msg_sender
function, which identifies a unique caller based upon the call and/or transaction input data.
contract;
use std::{
address::Address,
assert::assert,
chain::auth::{AuthError, msg_sender},
identity::Identity,
result::*,
revert::revert,
};
abi MyOwnedContract {
fn receive(field_1: u64) -> bool;
}
const OWNER: b256 = 0x9ae5b658754e096e4d681c548daf46354495a437cc61492599e33fc64dcdc30c;
impl MyOwnedContract for Contract {
fn receive(field_1: u64) -> bool {
let sender: Result<Identity, AuthError> = msg_sender();
if let Identity::Address(addr) = sender.unwrap() {
assert(addr.into() == OWNER);
} else {
revert(0);
}
true
}
}
The msg_sender
function works as follows:
- If the caller is a contract, then
Result::Ok(Sender)
is returned with theContractId
sender variant. - If the caller is external (i.e. from a script), then all coin input owners in the transaction are checked. If all owners are the same, then
Result::Ok(Sender)
is returned with theAddress
sender variant. - If the caller is external and coin input owners are different, then the caller cannot be determined and a
Result::Err(AuthError)
is returned.