Skip to main content

EVM Globals

Skittles gives you access to blockchain context — information about who's calling your contract, when, and how. Import them from skittles and use them in your contracts.

Transaction Context

import { msg, block, tx } from "skittles";

msg

PropertyTypeDescription
msg.senderaddressThe wallet address that called your function
msg.valueuint256The amount of ETH sent with the call
msg.databytesThe raw data of the function call
class Token {
owner: address = msg.sender;

deposit(): void {
// Accessing msg.value makes this function payable
this.balances[msg.sender] += msg.value;
}
}

block

PropertyTypeDescription
block.timestampuint256The timestamp of the current block (in seconds since Unix epoch)
block.numberuint256The current block number
block.chainiduint256The chain ID (1 for Ethereum mainnet, etc.)
block.coinbaseaddressThe address of the block miner or validator
class Staking {
private depositTimestamps: Record<address, number> = {};

deposit(): void {
this.depositTimestamps[msg.sender] = block.timestamp;
}
}

tx

PropertyTypeDescription
tx.originaddressThe original sender of the transaction (the wallet that started it)
tx.gaspriceuint256The gas price of the transaction

self (Contract Address)

Use self to get the contract's own address. This is Skittles' equivalent of Solidity's address(this).

import { self, address } from "skittles";

let contractAddress: address = self;

self is an address value, so you can use it anywhere you'd use an address — in comparisons, as a function argument, or to send ETH:

import { self, msg, address } from "skittles";

class Vault {
public getContractAddress(): address {
return self;
}

public isSelf(addr: address): boolean {
return addr == self;
}

public deposit(to: address, amount: number): void {
to.transfer(amount);
}
}
tip

If you're coming from Solidity, prefer self instead of address(this). While address(this) is passed through to the underlying compiler, address is a type-only export in Skittles' TypeScript typings, so address(this) is not type-safe and will typically fail TypeScript checking and IntelliSense. self is a value-level address and gives you the clean, fully typed experience.

Address Balance

Use .balance on any address to read its ETH balance (in wei):

import { self, address, msg } from "skittles";

class Vault {
public getContractBalance(): number {
return self.balance;
}

public getBalance(addr: address): number {
return addr.balance;
}

public getSenderBalance(): number {
return msg.sender.balance;
}
}
note

The Skittles compiler fully supports .balance on any address-typed expression, but the TypeScript type stubs currently model address as string, so .balance may show a type error in your IDE. The compiled Solidity output is correct regardless.

ETH Transfers

Use .transfer(amount) on any address to send ETH from the contract:

import { address, msg } from "skittles";

class Vault {
public receive(): void {
// Accept ETH deposits
}

public withdraw(to: address, amount: number): void {
to.transfer(amount);
}

public refund(): void {
msg.sender.transfer(100);
}
}

The .transfer(amount) method sends the specified amount of wei and reverts if the transfer fails. The contract must have sufficient ETH balance.

Built In Functions

Import built in functions from "skittles":

import { bytes32, keccak256, sha256, ecrecover, abi, gasleft } from "skittles";

Hashing

FunctionDescription
keccak256(...)Compute Keccak256 hash of the packed encoding of the arguments
sha256(...)Compute SHA256 hash of the packed encoding of the arguments
hash(...)Alias for keccak256
let digest: bytes32 = keccak256(msg.sender, amount);

Hash functions return bytes32. The type is also inferred automatically:

const digest = keccak256(msg.sender, amount); // inferred as bytes32

ABI Encoding

FunctionDescription
abi.encode(...)Encode arguments using the ABI encoding specification
abi.encodePacked(...)Encode arguments using packed encoding (more compact)
abi.decode<[...]>(data)Decode ABI-encoded data back into typed values

Use type parameters to specify the types you want to decode into:

const [amount, addr] = abi.decode<[number, address]>(data);

This compiles to Solidity's abi.decode(data, (uint256, address)).

Cryptography

FunctionDescription
ecrecover(hash, v, r, s)Recover the signer's address from a message hash and signature. hash, r, and s are bytes32; returns address.

Math

FunctionDescription
Math.min(a, b)Return the smaller of two values
Math.max(a, b)Return the larger of two values
Math.sqrt(x)Compute the integer square root of a value
Math.pow(a, b)Raise a to the power b (same as a ** b)
addmod(x, y, k)Compute (x + y) % k with arbitrary precision (no overflow)
mulmod(x, y, k)Compute (x * y) % k with arbitrary precision (no overflow)
let smaller = Math.min(a, b);
let clamped = Math.min(Math.max(value, min), max);
let root = Math.sqrt(x);

Utilities

FunctionDescription
assert(condition)Assert that a condition is true (panics and reverts if false)
gasleft()Get the amount of gas remaining for the current transaction

String and Bytes Concatenation

FunctionDescription
string.concat(...)Concatenate multiple strings into one
bytes.concat(...)Concatenate multiple byte arrays into one

Template literals are automatically compiled to string.concat():

let greeting: string = `Hello ${name}!`;

Special Values

TypeScriptDescription
Number.MAX_VALUEThe maximum value for a uint256 (2^256 - 1)
nullRepresents zero/empty value (compiles to 0)
undefinedRepresents zero/empty value (compiles to 0)