Language Overview¶
SolScript is a high-level language designed for writing Solana smart contracts. It combines Solidity-style syntax with Solana's unique features.
Design Philosophy¶
- Familiarity - Solidity-like syntax for easy adoption
- Safety - Strong typing and compile-time checks
- Efficiency - Optimized for Solana's runtime
- Simplicity - Hide complexity, expose power
Basic Structure¶
A SolScript file consists of:
// Imports (optional)
import { IERC20 } from "@solana/token";
// Custom errors
error InsufficientFunds(uint256 available, uint256 required);
// Events
event Transfer(address indexed from, address indexed to, uint256 amount);
// Structs
struct User {
address wallet;
uint256 balance;
bool active;
}
// Enums
enum Status { Pending, Active, Completed }
// Interfaces
interface IToken {
function transfer(address to, uint256 amount) external returns (bool);
}
// Contract
contract MyContract {
// State variables
uint256 public totalSupply;
mapping(address => uint256) public balances;
// Constructor
constructor(uint256 initialSupply) {
totalSupply = initialSupply;
}
// Functions
function transfer(address to, uint256 amount) public {
// Implementation
}
}
Key Concepts¶
Contracts¶
Contracts are the main building blocks. Each contract:
- Has state variables (on-chain storage)
- Has functions (entry points)
- Can emit events
- Can inherit from other contracts
State Variables¶
State is stored on-chain in Solana accounts:
uint256 public totalSupply; // Simple value
mapping(address => uint256) balances; // Key-value store (PDA)
User[] public users; // Dynamic array
Functions¶
Functions define contract behavior:
// Public - callable by anyone
function transfer(address to, uint256 amount) public { }
// External - only callable from outside
function deposit() external payable { }
// View - read-only, no state changes
function balanceOf(address account) public view returns (uint256) { }
// Pure - no state access at all
function add(uint256 a, uint256 b) public pure returns (uint256) { }
Built-in Objects¶
SolScript provides several built-in objects:
| Object | Description | Status |
|---|---|---|
msg.sender | Transaction signer | ✅ Works |
msg.value | SOL amount sent | ⚠️ Returns 0 (see limitations) |
block.timestamp | Current Unix timestamp | ✅ Works |
block.number | Current Solana slot | ✅ Works |
msg.value Limitation
msg.value currently returns 0. Direct SOL transfers are not yet supported. Use wrapped SOL (SPL Token) for value transfers. See the roadmap for planned improvements.
Control Flow¶
Standard control flow statements:
// If-else
if (condition) {
// ...
} else if (other) {
// ...
} else {
// ...
}
// For loop
for (uint256 i = 0; i < 10; i++) {
// ...
}
// While loop
while (condition) {
// ...
}
// Ternary
uint256 max = a > b ? a : b;
Error Handling¶
// Require - revert with message
require(amount > 0, "Amount must be positive");
// Custom errors
error InsufficientBalance(uint256 available, uint256 required);
// Revert with custom error
if (balance < amount) {
revert InsufficientBalance(balance, amount);
}
Solana-Specific Features¶
Accounts and PDAs¶
SolScript automatically handles Solana's account model:
// Mappings become PDAs automatically
mapping(address => uint256) public balances;
// Access like normal Solidity - SolScript handles PDA derivation
balances[user] = 100; // Creates PDA with seeds [b"balances", user]
This is SolScript's most powerful feature - you write Solidity-style mappings and get proper Solana PDAs.
Cross-Program Invocation (CPI)¶
Call other Solana programs via interfaces:
interface ITokenProgram {
function transfer(address from, address to, uint256 amount) external;
}
contract MyContract {
function sendTokens(address token, address to, uint256 amount) public {
ITokenProgram(token).transfer(msg.sender, to, amount);
}
}
SPL Token Built-ins¶
SolScript has native SPL Token support:
// These generate proper CPI calls to SPL Token program
tokenTransfer(from, to, amount);
tokenMint(mint, to, amount);
tokenBurn(account, amount);
Signers¶
Require additional transaction signatures:
function withdraw(signer authority, uint256 amount) public {
require(authority == owner, "Unauthorized");
// authority becomes a Signer<'info> in generated Anchor code
}
Time-Based Logic¶
Access Solana's clock sysvar:
function isExpired(uint64 deadline) public view returns (bool) {
return block.timestamp >= deadline;
}
For more details, see Solana Concepts.
Type System¶
SolScript has a strong type system:
| Category | Types |
|---|---|
| Integers | uint8 to uint256, int8 to int256 |
| Boolean | bool |
| Address | address |
| String | string |
| Bytes | bytes, bytes32 |
| Arrays | T[], T[N] |
| Mappings | mapping(K => V) |
Visibility¶
| Modifier | Accessible From |
|---|---|
public | Anywhere |
private | Same contract only |
internal | Same contract + derived |
external | Outside only |
Modifiers¶
Reusable access control:
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
function withdraw() public onlyOwner {
// Only owner can call
}