Gasgnome is a collection of Solidity libraries in inline assembly. The libraries provided aim to enhance functionality and efficiency in areas such as arithmetic operations, bitmask handling, contract interactions, error handling, event logging, and memory management.
To install Gasgnome, use the following command:
forge soldeer install gasgnome
To use these libraries in your project, import the required library file into your Solidity contract.
ArithmeticLib
provides functions for manipulating and converting data with specific bit sizes. It includes:
convertWithSize(bytes32 b, uint16 desiredBits, uint16 sizeInBits)
: Converts abytes32
value to a desired bit size, with error handling for invalid sizes.cap(uint16 bitSize)
: Computes the nearest bit cap in multiples of eight.
import { ArithmeticLib } from "gasgnome";
contract Example {
function exampleFunction(bytes32 value, uint16 desiredBits) public pure returns (bytes32) {
return ArithmeticLib.convertWithSize(value, desiredBits, 256);
}
}
BitmaskLib
provides functionality for working with bitmasks, including building masks and updating data with padding. It includes:
build(uint8 bits)
: Creates a mask with a specified number of bits.build(uint8 bits, uint8 leftShiftedBits)
: Creates a mask with a specified number of bits and left-shifted bits.updateLeftPadded(Mask memory m, bytes32 slot, bytes32 data)
: Updates data in storage with left padding.updateRightPadded(Mask memory m, bytes32 slot, bytes32 data)
: Updates data in storage with right padding.
import { BitmaskLib, Mask } from "gasgnome";
contract Example {
function exampleFunction(Mask memory mask, bytes32 slot, bytes32 data) public {
mask.updateLeftPadded(slot, data);
}
}
ContractLib
provides utilities for interacting with other contracts, including sending ether, calling functions, and handling return values. It includes:
call(Contract c, uint256 amount)
: Sends ether to a contract.call(Contract c, uint256 amount, FunctionSignature sig, bool hasOutput)
: Sends ether, calls a function, and optionally gets return value.staticcall(Contract c, FunctionSignature sig)
: Performs a static call to a contract.delegatecall(Contract c, FunctionSignature sig, bool hasOutput)
: Performs a delegate call to a contract.balance(Contract c)
: Gets the balance of a contract.
import { Contract, ContractLib } from "gasgnome";
contract Example {
function exampleFunction(Contract c) public {
c.call(1 ether);
}
}
ErrorLib
provides functions for handling and reverting with errors. It includes:
toErrorArgs(bytes32[] memory args)
: Converts an array of error arguments toErrorArg[]
.toErrorSelector(bytes memory ctx)
: Converts a context to anErrorSelector
.revertError()
: Reverts with no error data.revertError(ErrorSelector es)
: Reverts with an error selector.revertError(ErrorSelector es, ErrorArg[] memory eas)
: Reverts with an error selector and arguments.
import { ErrorLib, ErrorSelector } from "gasgnome";
contract Example {
function exampleFunction() public pure {
ErrorSelector(0x12345678).revertError();
}
}
EventLib
provides functionality for emitting events with various configurations. It includes:
emitEvent(EventHash eventHash)
: Emits a non-anonymous event with no data.emitEvent(EventHash eventHash, EventArgNonIndexed[] memory nonIndexedArgs)
: Emits a non-anonymous event with non-indexed arguments.emitEvent(EventHash eventHash, EventArgIndexed[1] memory indexedArgs)
: Emits a non-anonymous event with one indexed argument.emitEvent(EventHash eventHash, EventArgIndexed[1] memory indexedArgs, EventArgNonIndexed[] memory nonIndexedArgs)
: Emits a non-anonymous event with one indexed and non-indexed arguments.
import { EventLib } from "gasgnome";
contract Example {
event ExampleEvent(address indexed sender, uint256 value);
function exampleFunction() public {
EventLib.emitEvent(keccak256("ExampleEvent(address,uint256)"), [bytes32(uint256(uint160(msg.sender)))], [bytes32(uint256(42))]);
}
}
MemoryLib
provides functions for managing and manipulating memory. It includes:
freeMemory()
: Returns the current free memory pointer.nextFreeMemory()
: Returns the next free memory pointer.store(bytes32 data)
: Storesdata
in memory and returns the next free memory pointer.store(bytes32 data, bool isImmutable)
: Storesdata
in memory with optional immutability and returns the next free memory pointer.update(bytes32 ptr, bytes32 data)
: Updates the data at the specified memory pointer.memoryStorageLocation(bytes32 ptr)
: Computes the storage location of a given memory pointer.
import { MemoryLib } from "gasgnome";
contract Example {
function exampleFunction(bytes32 data) public pure returns (bytes32) {
bytes32 ptr = MemoryLib.store(data);
MemoryLib.update(ptr, data);
return MemoryLib.nextFreeMemory();
}
}
PointerLib
provides utilities for managing memory pointers. It includes:
load(Pointer ptr)
: Loads data from a memory pointer.next(Pointer ptr)
: Returns the next memory pointer.store(Pointer ptr, bytes32 data)
: Stores data at a memory pointer and returns the next pointer.store(Pointer ptr, bytes32 data, bool isImmutable)
: Stores data at a memory pointer with immutability flag and returns the next pointer.update(Pointer ptr, bytes32 data)
: Updates data at a memory pointer.memoryStorageLocation(Pointer ptr)
: Retrieves the memory storage location for a pointer.
import { Pointer, PointerLib } from "gasgnome";
contract Example {
function exampleFunction(Pointer ptr, bytes32 data) public pure {
ptr.store(data);
}
}
StorageLib
provides functions for accessing storage slots in different formats. It includes:
getSlot(address slot)
: Gets a storage slot from anaddress
.getSlot(int256 slot)
: Gets a storage slot from anint256
.getSlot(uint256 slot)
: Gets a storage slot from auint256
.getSlot(bytes32 slot)
: Gets a storage slot from abytes32
.getSlot(bytes storage ptr)
: Gets a storage slot from abytes
storage pointer.getSlot(string storage ptr)
: Gets a storage slot from astring
storage pointer.
import { Slot, StorageLib } from "gasgnome";
contract Example {
function exampleFunction(address slot) public pure returns (Slot storage s) {
return StorageLib.getSlot(slot);
}
}
SignedIntLib
provides arithmetic functions for signed integers and includes:
addSignedInt(SignedInt left, SignedInt right)
: Adds two signed integers.subSignedInt(SignedInt left, SignedInt right)
: Subtracts one signed integer from another.mulSignedInt(SignedInt left, SignedInt right)
: Multiplies two signed integers.divSignedInt(SignedInt left, SignedInt right)
: Divides one signed integer by another.modSignedInt(SignedInt left, SignedInt right)
: Computes the modulus of two signed integers.expSignedInt(SignedInt left, SignedInt right)
: Computes the exponentiation of two signed integers.convertWithSize(SignedInt u, uint16 desiredBits)
: Converts a signed integer to a desired bit size.sizeInBits(SignedInt s)
: Computes the bit size of a signed integer.
import { SignedInt, SignedIntLib } from "gasgnome";
contract Example {
function exampleFunction(SignedInt a, SignedInt b) public pure returns (SignedInt) {
return a + b;
}
}
SlotLib
provides utilities for interacting with storage slots. It includes:
asAddress(Slot storage s)
: Retrieves an address from a storage slot.asBoolean(Slot storage s)
: Retrieves a boolean from a storage slot.asBytes32(Slot storage s)
: Retrieves abytes32
value from a storage slot.asInt256(Slot storage s)
: Retrieves anint256
value from a storage slot.asUint256(Slot storage s)
: Retrieves auint256
value from a storage slot.asBytes(Slot storage s)
: Retrieves abytes
value from a storage slot.asString(Slot storage s)
: Retrieves astring
from a storage slot.AddressSlot
,BooleanSlot
,Bytes32Slot
,Int256Slot
, andUint256Slot
: Types for handling different slot types with transient storage operations.
import { Slot } from "gasgnome";
contract Example {
Slot private mySlot;
function exampleFunction() public view returns (address) {
return mySlot.asAddress();
}
}
UnsignedIntLib
provides arithmetic functions for unsigned integers and includes:
addUnsignedInt(UnsignedInt left, UnsignedInt right)
: Adds two unsigned integers.subUnsignedInt(UnsignedInt left, UnsignedInt right)
: Subtracts one unsigned integer from another.mulUnsignedInt(UnsignedInt left, UnsignedInt right)
: Multiplies two unsigned integers.divUnsignedInt(UnsignedInt left, UnsignedInt right)
: Divides one unsigned integer by another.modUnsignedInt(UnsignedInt left, UnsignedInt right)
: Computes the modulus of two unsigned integers.expUnsignedInt(UnsignedInt left, UnsignedInt right)
: Computes the exponentiation of two unsigned integers.convertWithSize(UnsignedInt u, uint16 desiredBits)
: Converts an unsigned integer to a desired bit size.sizeInBits(UnsignedInt u)
: Computes the bit size of an unsigned integer.
import { UnsignedInt } from "gasgnome";
contract Example {
function exampleFunction(UnsignedInt a, UnsignedInt b) public pure returns (UnsignedInt) {
return a + b;
}
}
Feel free to contribute to the Gasgnome project by submitting issues or pull requests on GitHub. Your contributions and feedback are greatly appreciated.
This project is licensed under the MIT license.