在 Sway 中,智能合约需要能够限制对某些用户或合约的访问。与基于账户的区块链不同,基于 UTXO 的区块链(例如 Fuel)中的交易不一定有一个唯一的交易发送者。需要额外的逻辑来处理这种差异,并由标准库提供支持。
msg_sender
为了提供类似于 EVM 中的访问控制体验,std
库提供了一个 msg_sender
函数,该函数基于调用和/或交易输入数据来标识一个唯一的调用者。
contract;
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
}
}
msg_sender
函数的工作原理如下:
ContractId
发送者变体的 Ok(Sender)
。 Address
发送者变体的 Ok(Sender)
。 Err(AuthError)
。 许多合约需要某种形式的所有权以进行访问控制。SRC-5 拥有权标准 已经定义了一个可互操作的合约内部所有权接口。
为了实现这一点,使用 Ownership 库 来跟踪所有者。这允许使用变体 Some(..)
和 None
来设置和撤销所有权。这比直接使用 Identity
类型更好、更安全、更可读,其中撤销所有权必须使用某些魔术值如 b256::zero()
或其他方式。
以下是正确锁定函数以使只有所有者可以调用函数的示例:
#[storage(read)]
fn only_owner() {
storage.owner.only_owner();
// Do stuff here
}
设置所有权可以通过两种方式之一来完成:在编译时或运行时。
以下是在编译时正确设置合约所有权的示例:
storage {
owner: Ownership = Ownership::initialized(Identity::Address(Address::zero())),
}
以下是在运行时正确设置合约所有权的示例:
#[storage(write)]
fn set_owner(identity: Identity) {
storage.owner.set_ownership(identity);
}
以下是正确撤销合约所有权的示例:
#[storage(write)]
fn revoke_ownership() {
storage.owner.renounce_ownership();
}
以下是正确检索所有权状态的示例:
#[storage(read)]
fn owner() -> State {
storage.owner.owner()
}
Sway-Libs 提供以下库以进一步实现访问控制。