Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce Self::zero and self::is_zero() for 13 types #5973

Merged
merged 23 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/book/src/blockchain-development/access_control.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ The `msg_sender` function works as follows:

Many contracts require some form of ownership for access control. The [SRC-5 Ownership Standard](https://github.com/FuelLabs/sway-standards/blob/master/SRCs/src-5.md) has been defined to provide an interoperable interface for ownership within contracts.

To accomplish this, use the [Ownership Library](https://fuellabs.github.io/sway-libs/book/ownership/index.html) 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.
To accomplish this, use the [Ownership Library](https://fuellabs.github.io/sway-libs/book/ownership/index.html) 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 `b256::zero()` or otherwise.

- The following is an example of how to properly lock a function such that only the owner may call a function:

Expand Down
2 changes: 1 addition & 1 deletion docs/book/src/blockchain-development/native_assets.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ In the case where the `b256` value of an asset is already known, you may call th

The SubId is used to differentiate between different assets that are created by the same contract. The `SubId` is a `b256` value.

When creating an single new asset on Fuel, we recommend using the `DEFAULT_ASSET_ID`.
When creating an single new asset on Fuel, we recommend using the `DEFAULT_SUB_ID` or `SubId::zero()`.
bitzoic marked this conversation as resolved.
Show resolved Hide resolved

## The Base Asset

Expand Down
2 changes: 1 addition & 1 deletion docs/book/src/sway-program-types/smart_contracts.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,4 @@ Each special parameter is optional and assumes a default value when skipped:

1. The default value for `gas` is the context gas (i.e. the content of the special register `$cgas`). Refer to the [FuelVM specifications](https://fuellabs.github.io/fuel-specs/master/vm) for more information about context gas.
2. The default value for `coins` is 0.
3. The default value for `asset_id` is `ZERO_B256`.
3. The default value for `asset_id` is `b256::zero()`.
14 changes: 6 additions & 8 deletions docs/reference/src/code/operations/asset_operations/src/lib.sw
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,10 @@ use std::asset::burn;
use std::asset::transfer;
// ANCHOR_END: transfer_import

use std::constants::ZERO_B256;

fn minting() {
// ANCHOR: mint
let amount = 10;
mint(ZERO_B256, amount);
mint(SubId::zero(), amount);
// ANCHOR_END: mint
}

Expand All @@ -28,7 +26,7 @@ fn minting_to_address() {
let address = 0x0000000000000000000000000000000000000000000000000000000000000001;
let user = Address::from(address);

mint_to(Identity::Address(user), ZERO_B256, amount);
mint_to(Identity::Address(user), SubId::zero(), amount);
// ANCHOR_END: mint_to_address
}

Expand All @@ -38,7 +36,7 @@ fn minting_to_contract() {
let address = 0x0000000000000000000000000000000000000000000000000000000000000001;
let pool = ContractId::from(address);

mint_to(Identity::ContractId(pool), ZERO_B256, amount);
mint_to(Identity::ContractId(pool), SubId::zero(), amount);
// ANCHOR_END: mint_to_contract
}

Expand All @@ -49,15 +47,15 @@ fn minting_to() {
let user = Identity::Address(Address::from(address));
let pool = Identity::ContractId(ContractId::from(address));

mint_to(user, ZERO_B256, amount);
mint_to(pool, ZERO_B256, amount);
mint_to(user, SubId::zero(), amount);
mint_to(pool, SubId::zero(), amount);
// ANCHOR_END: mint_to
}

fn burning() {
// ANCHOR: burn
let amount = 10;
burn(ZERO_B256, amount);
burn(SubId::zero(), amount);
// ANCHOR_END: burn
}

Expand Down
7 changes: 3 additions & 4 deletions examples/advanced_storage_variables/src/main.sw
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ contract;

use std::{
bytes::Bytes,
constants::ZERO_B256,
hash::Hash,
storage::{
storage_bytes::*,
Expand Down Expand Up @@ -81,19 +80,19 @@ impl StorageExample for Contract {
.push(0x0000000000000000000000000000000000000000000000000000000000000002);

// Set will overwrite the element stored at the given index.
storage.storage_vec.set(2, ZERO_B256);
storage.storage_vec.set(2, b256::zero());
// ANCHOR_END: vec_storage_write
}
#[storage(read, write)]
fn get_vec() {
// ANCHOR: vec_storage_read
// Method 1: Access the element directly
// Note: get() does not remove the element from the vec.
let stored_val1: b256 = storage.storage_vec.get(0).unwrap().try_read().unwrap_or(ZERO_B256);
let stored_val1: b256 = storage.storage_vec.get(0).unwrap().try_read().unwrap_or(b256::zero());

// Method 2: First get the storage key and then access the value.
let storage_key2: StorageKey<b256> = storage.storage_vec.get(1).unwrap();
let stored_val2: b256 = storage_key2.try_read().unwrap_or(ZERO_B256);
let stored_val2: b256 = storage_key2.try_read().unwrap_or(b256::zero());

// pop() will remove the last element from the vec.
let length: u64 = storage.storage_vec.len();
Expand Down
10 changes: 4 additions & 6 deletions examples/basic_storage_variables/src/main.sw
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
contract;

use std::constants::ZERO_B256;

// ANCHOR: basic_storage_declaration
storage {
var1: u64 = 1,
var2: b256 = ZERO_B256,
var3: Address = Address::from(ZERO_B256),
var2: b256 = b256::zero(),
var3: Address = Address::zero(),
var4: Option<u8> = None,
}
// ANCHOR_END: basic_storage_declaration
Expand Down Expand Up @@ -37,8 +35,8 @@ impl StorageExample for Contract {
fn get_something() {
// ANCHOR: basic_storage_read
let var1: u64 = storage.var1.read();
let var2: b256 = storage.var2.try_read().unwrap_or(ZERO_B256);
let var3: Address = storage.var3.try_read().unwrap_or(Address::from(ZERO_B256));
let var2: b256 = storage.var2.try_read().unwrap_or(b256::zero());
let var3: Address = storage.var3.try_read().unwrap_or(Address::zero());
let var4: Option<u8> = storage.var4.try_read().unwrap_or(None);
// ANCHOR_END: basic_storage_read
}
Expand Down
4 changes: 2 additions & 2 deletions examples/identity/src/main.sw
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ mod errors;
use abi::IdentityExample;
use errors::MyError;

use std::{asset::transfer, constants::{ZERO_B256,},};
use std::asset::transfer;

storage {
owner: Identity = Identity::ContractId(ContractId::from(ZERO_B256)),
owner: Identity = Identity::ContractId(ContractId::zero()),
}

impl IdentityExample for Contract {
Expand Down
1 change: 0 additions & 1 deletion examples/nested_storage_variables/src/main.sw
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ contract;

use std::{
bytes::Bytes,
constants::ZERO_B256,
hash::{
Hash,
sha256,
Expand Down
4 changes: 1 addition & 3 deletions examples/ownership/src/main.sw
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
contract;

use std::constants::ZERO_B256;

// SRC-5 Ownership Standard `State` enum
pub enum State {
Uninitialized: (),
Expand Down Expand Up @@ -46,7 +44,7 @@ abi OwnershipExample {

// ANCHOR: set_owner_example_storage
storage {
owner: Ownership = Ownership::initialized(Identity::Address(Address::from(ZERO_B256))),
owner: Ownership = Ownership::initialized(Identity::Address(Address::zero())),
}
// ANCHOR_END: set_owner_example_storage

Expand Down
3 changes: 1 addition & 2 deletions examples/wallet_contract_caller_script/src/main.sw
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
script;

use std::constants::ZERO_B256;
use wallet_abi::Wallet;

fn main() {
Expand All @@ -12,6 +11,6 @@ fn main() {
.send_funds {
gas: 10000,
coins: 0,
asset_id: ZERO_B256,
asset_id: b256::zero(),
}(amount_to_send, recipient_address);
}
4 changes: 1 addition & 3 deletions sway-lib-core/src/primitives.sw
Original file line number Diff line number Diff line change
Expand Up @@ -295,11 +295,9 @@ impl b256 {
/// # Examples
///
/// ```sway
/// use std::constants::ZERO_B256;
///
/// fn foo() {
/// let val = b256::min();
/// assert(val == ZERO_B256);
/// assert(val == b256::zero());
/// }
/// ```
pub fn min() -> Self {
Expand Down
22 changes: 11 additions & 11 deletions sway-lib-core/src/storage.sw
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ impl<T> StorageKey<T> {
/// # Examples
///
/// ```sway
/// use std::{constants::ZERO_B256, hash::sha256};
/// use std::hash::sha256;
///
/// fn foo() {
/// let my_key = StorageKey::<u64>::new(ZERO_B256, 0, sha256(ZERO_B256));
/// assert(my_key.slot() == ZERO_B256);
/// let my_key = StorageKey::<u64>::new(b256::zero(), 0, sha256(b256::zero()));
/// assert(my_key.slot() == b256::zero());
/// }
/// ```
pub fn new(slot: b256, offset: u64, field_id: b256) -> Self {
Expand All @@ -59,11 +59,11 @@ impl<T> StorageKey<T> {
/// # Examples
///
/// ```sway
/// use std::{constants::ZERO_B256, hash::sha256};
/// use std::hash::sha256;
///
/// fn foo() {
/// let my_key = StorageKey::<u64>::new(ZERO_B256, 0, sha256(ZERO_B256));
/// assert(my_key.slot() == ZERO_B256);
/// let my_key = StorageKey::<u64>::new(b256::zero(), 0, sha256(b256::zero()));
/// assert(my_key.slot() == b256::zero());
/// }
/// ```
pub fn slot(self) -> b256 {
Expand All @@ -79,10 +79,10 @@ impl<T> StorageKey<T> {
/// # Examples
///
/// ```sway
/// use std::{constants::ZERO_B256, hash::sha256};
/// use std::hash::sha256;
///
/// fn foo() {
/// let my_key = StorageKey::<u64>::new(ZERO_B256, 0, sha256(ZERO_B256));
/// let my_key = StorageKey::<u64>::new(b256::zero(), 0, sha256(b256::zero()));
/// assert(my_key.offset() == 0);
/// }
/// ```
Expand All @@ -105,11 +105,11 @@ impl<T> StorageKey<T> {
/// # Examples
///
/// ```sway
/// use std::{constants::ZERO_B256, hash::sha256};
/// use std::hash::sha256;
///
/// fn foo() {
/// let my_key = StorageKey::<u64>::new(ZERO_B256, 0, sha256(ZERO_B256));
/// assert(my_key.field_id() == sha256(ZERO_B256));
/// let my_key = StorageKey::<u64>::new(b256::zero(), 0, sha256(b256::zero()));
/// assert(my_key.field_id() == sha256(b256::zero()));
/// }
/// ```
pub fn field_id(self) -> b256 {
Expand Down
57 changes: 46 additions & 11 deletions sway-lib-std/src/address.sw
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ library;

use ::convert::From;
use ::hash::{Hash, Hasher};
use ::zero::Zero;

/// The `Address` type, a struct wrapper around the inner `b256` value.
pub struct Address {
Expand All @@ -20,11 +21,9 @@ impl Address {
/// # Examples
///
/// ```sway
/// use std::constants::ZERO_B256;
///
/// fn foo() -> {
/// let my_address = Address::from(ZERO_B256);
/// assert(my_address.bits() == ZERO_B256);
/// let my_address = Address::zero();
/// assert(my_address.bits() == b256::zero());
/// }
/// ```
pub fn bits(self) -> b256 {
Expand Down Expand Up @@ -53,10 +52,8 @@ impl From<b256> for Address {
/// # Examples
///
/// ```sway
/// use std::constants::ZERO_B256;
///
/// fn foo() {
/// let address = Address::from(ZERO_B256);
/// let address = Address::from(b256::zero());
/// }
/// ```
fn from(bits: b256) -> Self {
Expand All @@ -74,12 +71,10 @@ impl From<Address> for b256 {
/// # Examples
///
/// ```sway
/// use std::constants::ZERO_B256;
///
/// fn foo() {
/// let address = Address::from(ZERO_B256);
/// let address = Address::zero();
/// let b256_data: b256 = address.into();
/// assert(b256_data == ZERO_B256);
/// assert(b256_data == b256::zero());
/// }
/// ```
fn from(address: Address) -> Self {
Expand All @@ -94,6 +89,46 @@ impl Hash for Address {
}
}

impl Zero for Address {
/// Returns the zero value for the `Address` type.
///
/// # Returns
///
/// * [Address] -> The zero value for the `Address` type.
///
/// # Examples
///
/// ```sway
/// fn foo() {
/// let zero_address = Address::zero();
/// assert(zero_address == Address:from(b256::zero()));
/// }
/// ```
fn zero() -> Self {
Self {
bits: b256::zero(),
}
}

/// Returns whether an `Address` is set to zero.
///
/// # Returns
///
/// * [bool] -> True if the `Address` is zero, otherwise false.
///
/// # Examples
///
/// ```sway
/// fn foo() {
/// let zero_address = Address::zero();
/// assert(zero_address.is_zero());
/// }
/// ```
fn is_zero(self) -> bool {
self.bits == b256::zero()
}
}

#[test]
fn test_address_from_b256() {
use ::assert::assert;
Expand Down