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.
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::auth::msg_sender;
abi MyOwnedContract {
fn receive(field_1: u64) -> bool;
}
const OWNER = Address::from(0x9ae5b658754e096e4d681c548daf46354495a437cc61492599e33fc64dcdc30c);
impl MyOwnedContract for Contract {
fn receive(field_1: u64) -> bool {
let sender = msg_sender().unwrap();
if let Identity::Address(addr) = sender {
assert(addr == OWNER);
} else {
revert(0);
}
true
}
}
The msg_sender function works as follows:
msg_sender函数的工作原理如下:
If the caller is a contract, then Result::Ok(Sender) is returned with the ContractId sender variant.
如果调用者是一个合约,那么Result::Ok(Sender)将被返回,并带有ContractId的发送者变量。
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 the Address sender variant.
如果调用者是外部的(即来自脚本),那么将检查交易中所有代币输入的所有者。如果所有所有者都是相同的,那么Result::Ok(Sender)将以Address发件人变量返回。
If the caller is external and coin input owners are different, then the caller cannot be determined and a Result::Err(AuthError) is returned.
如果调用者是外部的,而代币输入所有者是不同的,那么调用者就无法确定,并返回`Result::Err(AuthError)'。
合约所有权 (Contract Ownership)
Many contracts require some form of ownership for access control. To accomplish this, it is recommended that a storage variable of type Option<Identity> is used to keep track of the owner. This allows setting and revoking ownership using the variants Some(..) and None respectively. This is better, safer, and more readable than using the Identity type directly where revoking ownership has to be done using some magic value such as std::constants::ZERO_B256 or otherwise.