Skip to content

Commit

Permalink
General code quality enhancements to the standard library (FuelLabs#2431
Browse files Browse the repository at this point in the history
)

General enhancements to the standard library
  • Loading branch information
mohammadfawaz authored Jul 31, 2022
1 parent 376010e commit 33faa76
Show file tree
Hide file tree
Showing 17 changed files with 94 additions and 115 deletions.
2 changes: 0 additions & 2 deletions sway-lib-std/src/assert.sw
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,5 @@ use ::revert::revert;
pub fn assert(condition: bool) {
if !condition {
revert(0);
} else {
()
}
}
43 changes: 23 additions & 20 deletions sway-lib-std/src/chain/auth.sw
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use ::contract_id::ContractId;
use ::identity::Identity;
use ::option::Option;
use ::result::Result;
use ::tx::{tx_inputs_count, tx_input_type, tx_input_owner, INPUT_COIN, INPUT_MESSAGE};
use ::tx::{INPUT_COIN, INPUT_MESSAGE, tx_input_owner, tx_input_type, tx_inputs_count};

pub enum AuthError {
InputsNotAllOwnedBySameAddress: (),
Expand Down Expand Up @@ -57,26 +57,29 @@ fn inputs_owner() -> Result<Identity, AuthError> {
if input_type != INPUT_COIN && input_type != INPUT_MESSAGE {
// type != InputCoin or InputMessage, continue looping.
i += 1;
} else {
// type == InputCoin or InputMessage
let input_owner = tx_input_owner(i);
if candidate.is_none() {
// This is the first input seen of the correct type.
candidate = input_owner;
i += 1;
} else {
// Compare current input owner to candidate.
// `candidate` and `input_owner` must be `Option::Some`
// at this point, so we can unwrap safely.
if input_owner.unwrap() == candidate.unwrap() {
// Owners are a match, continue looping.
i += 1;
} else {
// Owners don't match. Return Err.
return Result::Err(AuthError::InputsNotAllOwnedBySameAddress);
};
};
continue;
}

// type == InputCoin or InputMessage
let input_owner = tx_input_owner(i);
if candidate.is_none() {
// This is the first input seen of the correct type.
candidate = input_owner;
i += 1;
continue;
}

// Compare current input owner to candidate.
// `candidate` and `input_owner` must be `Option::Some`
// at this point, so we can unwrap safely.
if input_owner.unwrap() == candidate.unwrap() {
// Owners are a match, continue looping.
i += 1;
continue;
}

// Owners don't match. Return Err.
return Result::Err(AuthError::InputsNotAllOwnedBySameAddress);
}

// `candidate` must be `Option::Some` at this point, so can unwrap safely.
Expand Down
2 changes: 1 addition & 1 deletion sway-lib-std/src/context.sw
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ dep context/registers;
dep context/call_frames;

use ::contract_id::ContractId;
use ::context::call_frames::*;
use ::context::call_frames::contract_id;
use ::context::registers::balance;

/// Get the balance of coin `asset_id` for the current contract.
Expand Down
7 changes: 3 additions & 4 deletions sway-lib-std/src/context/call_frames.sw
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
/// https://github.com/FuelLabs/fuel-specs/blob/master/specs/vm/main.md#call-frames
library call_frames;

use ::contract_id::ContractId;
use ::mem::read;
use ::context::registers::frame_ptr;
use ::contract_id::ContractId;
use ::intrinsics::is_reference_type;
use ::mem::read;

// Note that everything when serialized is padded to word length.
//
Expand Down Expand Up @@ -58,8 +58,7 @@ pub fn first_param() -> u64 {
pub fn second_param<T>() -> T {
if !is_reference_type::<T>() {
read::<T>(frame_ptr() + SECOND_PARAMETER_OFFSET)
}
else {
} else {
read::<T>(read::<u64>(frame_ptr() + SECOND_PARAMETER_OFFSET))
}
}
Expand Down
2 changes: 1 addition & 1 deletion sway-lib-std/src/ecr.sw
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use ::address::Address;
use ::b512::B512;
use ::context::registers::error;
use ::hash::sha256;
use ::result::*;
use ::result::Result;

pub enum EcRecoverError {
UnrecoverablePublicKey: (),
Expand Down
10 changes: 4 additions & 6 deletions sway-lib-std/src/flags.sw
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ use ::context::registers::flags;
/// IMPORTANT !!! Don't forget to call enable_panic_on_overflow() after performing the operations for which you disabled the default panic-on-overflow behavior in the first place !
pub fn disable_panic_on_overflow() {
// Mask second bit, which is `F_WRAPPING`.
// TODO can't use binary literal: https://github.com/FuelLabs/sway/issues/1664
// 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000010
let mask = 2;
let mask = 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000010;

// Get the current value of the flags register and mask it, setting the
// masked bit. Flags are inverted, so set = off.
let flag_val = flags() | mask;
Expand All @@ -21,9 +20,8 @@ pub fn disable_panic_on_overflow() {
/// Call this function to re-enable the panic-on-overflow behavior in the FuelVM. Note that panic-on-overflow is the default, so there is no need to use this function unless you have previously called disable_panic_on_overflow().
pub fn enable_panic_on_overflow() {
// Mask second bit, which is `F_WRAPPING`.
// TODO can't use binary literal: https://github.com/FuelLabs/sway/issues/1664
// 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111101
let mask = 18446744073709551613;
let mask = 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111101;

// Get the current value of the flags register and mask it, unsetting the
// masked bit. Flags are inverted, so unset = on.
let flag_val = flags() & mask;
Expand Down
2 changes: 1 addition & 1 deletion sway-lib-std/src/mem.sw
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! Library for working with memory.
library mem;

use ::revert::revert;
use ::intrinsics::{is_reference_type, size_of_val};
use ::revert::revert;

/// Returns the address of the given value.
pub fn addr_of<T>(val: T) -> u64 {
Expand Down
2 changes: 1 addition & 1 deletion sway-lib-std/src/option.sw
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use ::revert::revert;
pub enum Option<T> {
/// Signifies the absence of a value
None: (),

/// Contains the value
Some: T,
}
Expand Down
3 changes: 1 addition & 2 deletions sway-lib-std/src/reentrancy.sw
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
library reentrancy;

use ::context::call_frames::*;
use ::assert::assert;
use ::context::registers::frame_ptr;
use ::context::{call_frames::*, registers::frame_ptr};

pub fn reentrancy_guard() {
assert(!is_reentrant());
Expand Down
2 changes: 0 additions & 2 deletions sway-lib-std/src/revert.sw
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,5 @@ pub fn require<T>(condition: bool, value: T) {
if !condition {
log(value);
revert(FAILED_REQUIRE_SIGNAL)
} else {
()
}
}
74 changes: 32 additions & 42 deletions sway-lib-std/src/storage.sw
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use ::hash::sha256;
use ::option::Option;
use ::result::Result;


/// Store a stack variable in storage.
#[storage(write)]pub fn store<T>(key: b256, value: T) {
if !__is_reference_type::<T>() {
Expand All @@ -15,7 +14,7 @@ use ::result::Result;
sww k v;
};
} else {
// If reference type, then it's more than a word. Loop over every 32
// If reference type, then it can be more than a word. Loop over every 32
// bytes and store sequentially.
let mut size_left = __size_of::<T>();
let mut local_key = key;
Expand Down Expand Up @@ -58,7 +57,7 @@ use ::result::Result;
v: T
}
} else {
// If reference type, then it's more than a word. Loop over every 32
// If reference type, then it can be more than a word. Loop over every 32
// bytes and read sequentially.
let mut size_left = __size_of::<T>();
let mut local_key = key;
Expand Down Expand Up @@ -112,19 +111,19 @@ impl<K, V> StorageMap<K, V> {
}

/// A persistant vector struct
pub struct StorageVec<V> {}
pub struct StorageVec<V> {
}

impl<V> StorageVec<V> {
/// Appends the value to the end of the vector
///
///
/// # Arguments
///
///
/// * `value` - The item being added to the end of the vector
#[storage(read, write)]
pub fn push(self, value: V) {
#[storage(read, write)]pub fn push(self, value: V) {
// The length of the vec is stored in the __get_storage_key() slot
let len = get::<u64>(__get_storage_key());

// Storing the value at the current length index (if this is the first item, starts off at 0)
let key = sha256((len, __get_storage_key()));
store::<V>(key, value);
Expand All @@ -134,14 +133,13 @@ impl<V> StorageVec<V> {
}

/// Removes the last element of the vector and returns it, None if empty
#[storage(read, write)]
pub fn pop(self) -> Option<V> {
#[storage(read, write)]pub fn pop(self) -> Option<V> {
let len = get::<u64>(__get_storage_key());
// if the length is 0, there is no item to pop from the vec
if len == 0 {
return Option::None;
}

// reduces len by 1, effectively removing the last item in the vec
store(__get_storage_key(), len - 1);

Expand All @@ -150,12 +148,11 @@ impl<V> StorageVec<V> {
}

/// Gets the value in the given index, None if index is out of bounds
///
///
/// # Arguments
///
///
/// * `index` - The index of the vec to retrieve the item from
#[storage(read)]
pub fn get(self, index: u64) -> Option<V> {
#[storage(read)]pub fn get(self, index: u64) -> Option<V> {
let len = get::<u64>(__get_storage_key());
// if the index is larger or equal to len, there is no item to return
if len <= index {
Expand All @@ -169,19 +166,18 @@ impl<V> StorageVec<V> {
/// Removes the element in the given index and moves all the element in the following indexes
/// Down one index. Also returns the element
///
/// # WARNING
/// # WARNING
///
/// Expensive for larger vecs
///
/// # Arguments
///
///
/// * `index` - The index of the vec to remove the item from
///
/// # Reverts
///
///
/// Reverts if index is larger or equal to length of the vec
#[storage(read, write)]
pub fn remove(self, index: u64) -> V {
#[storage(read, write)]pub fn remove(self, index: u64) -> V {
let len = get::<u64>(__get_storage_key());
// if the index is larger or equal to len, there is no item to remove
assert(index < len);
Expand All @@ -197,7 +193,7 @@ impl<V> StorageVec<V> {
let key = sha256((count - 1, __get_storage_key()));
// moves the element of the current index into the previous index
store::<V>(key, get::<V>(sha256((count, __get_storage_key()))));

count += 1;
}

Expand All @@ -211,14 +207,13 @@ impl<V> StorageVec<V> {
/// Does not preserve ordering. Also returns the element
///
/// # Arguments
///
///
/// * `index` - The index of the vec to remove the item from
///
/// # Reverts
///
///
/// Reverts if index is larger or equal to length of the vec
#[storage(read, write)]
pub fn swap_remove(self, index: u64) -> V {
#[storage(read, write)]pub fn swap_remove(self, index: u64) -> V {
let len = get::<u64>(__get_storage_key());
// if the index is larger or equal to len, there is no item to remove
assert(index < len);
Expand All @@ -239,16 +234,15 @@ impl<V> StorageVec<V> {
/// Sets/mutates the value at the given index
///
/// # Arguments
///
///
/// * `index` - The index of the vec to set the value at
/// * `value` - The value to be set
///
/// # Reverts
///
///
/// Reverts if index is larger than or equal to the length of the vec
#[storage(read, write)]
pub fn set(self, index: u64, value: V) {
let len = get::<u64>(__get_storage_key());
#[storage(read, write)]pub fn set(self, index: u64, value: V) {
let len = get::<u64>(__get_storage_key());
// if the index is higher than or equal len, there is no element to set
assert(index < len);

Expand All @@ -259,20 +253,19 @@ impl<V> StorageVec<V> {
/// Inserts the value at the given index, moving the current index's value aswell as the following's
/// Up one index
///
/// # WARNING
/// # WARNING
///
/// Expensive for larger vecs
///
/// # Arguments
///
///
/// * `index` - The index of the vec to insert the item into
/// * `value` - The value to insert into the vec
///
/// # Reverts
///
///
/// Reverts if index is larger than length of the vec
#[storage(read, write)]
pub fn insert(self, index: u64, value: V) {
#[storage(read, write)]pub fn insert(self, index: u64, value: V) {
let len = get::<u64>(__get_storage_key());
// if the index is larger than len, there is no space to insert
assert(index <= len);
Expand Down Expand Up @@ -309,21 +302,18 @@ impl<V> StorageVec<V> {
}

/// Returns the length of the vector
#[storage(read)]
pub fn len(self) -> u64 {
#[storage(read)]pub fn len(self) -> u64 {
get::<u64>(__get_storage_key())
}

/// Checks whether the len is 0 or not
#[storage(read)]
pub fn is_empty(self) -> bool {
#[storage(read)]pub fn is_empty(self) -> bool {
let len = get::<u64>(__get_storage_key());
len == 0
}

/// Sets the len to 0
#[storage(write)]
pub fn clear(self) {
#[storage(write)]pub fn clear(self) {
store(__get_storage_key(), 0);
}
}
6 changes: 3 additions & 3 deletions sway-lib-std/src/token.sw
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
library token;

use ::address::Address;
use ::contract_id::ContractId;
use ::revert::revert;
use ::tx::*;
use ::context::call_frames::contract_id;
use ::contract_id::ContractId;
use ::identity::Identity;
use ::revert::revert;
use ::tx::{OUTPUT_VARIABLE, tx_output_amount, tx_output_type, tx_outputs_count};

/// Mint `amount` coins of the current contract's `asset_id` and transfer them
/// to `to` by calling either force_transfer_to_contract() or
Expand Down
Loading

0 comments on commit 33faa76

Please sign in to comment.