STT is the native token of the Somnia Network, similar to ETH on Ethereum. Unlike ERC20 tokens, STT is built into the protocol itself and does not have a contract address.
This multi-part guide shows how to use STT for:
Sponsored gas via Account Abstraction
Use STT for Payments in Smart Contracts
A simple contract that accepts exact STT payments:
Copy function payToAccess() external payable {
require(msg.value == 0.01 ether, "Must send exactly 0.01 STT");
}
Use msg.value
to access the native token sent in a transaction. No ERC20 functions are needed.
To withdraw collected STT:
Copy function withdraw() external onlyOwner {
payable(owner).transfer(address(this).balance);
}
Deploy using Hardhat Ignition or Viem and test with a sendTransaction
call.
Example.sol
Copy // SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract STTPayment {
address public owner;
constructor() {
owner = msg.sender;
}
// Modifier to restrict access to the contract owner
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can call this");
_;
}
// User must send exactly 0.01 STT to access this feature
function payToAccess() external payable {
require(msg.value == 0.01 ether, "Must send exactly 0.01 STT");
// Logic for access: mint token, grant download, emit event, etc.
}
// Withdraw collected STT to owner
function withdraw() external onlyOwner {
payable(owner).transfer(address(this).balance);
}
}
Build an STT Escrow Contract
A secure escrow contract allows a buyer to deposit STT and later release or refund:
Copy constructor(address payable _seller) payable {
buyer = msg.sender;
seller = _seller;
amount = msg.value;
}
Release funds to the seller:
Copy function release() external onlyBuyer {
seller.transfer(amount);
}
Deploy with Hardhat Ignition and pass STT as value
during deployment.
Example.sol
Copy // SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract STTEscrow {
address public buyer;
address payable public seller;
uint256 public amount;
bool public isDeposited;
constructor(address payable _seller) payable {
buyer = msg.sender;
seller = _seller;
amount = msg.value;
require(amount > 0, "Must deposit STT");
isDeposited = true;
}
modifier onlyBuyer() {
require(msg.sender == buyer, "Only buyer can call this");
_;
}
function release() external onlyBuyer {
require(isDeposited, "No funds to release");
isDeposited = false;
seller.transfer(amount);
}
function refund() external onlyBuyer {
require(isDeposited, "No funds to refund");
isDeposited = false;
payable(buyer).transfer(amount);
}
}
STT Tip Jar
Allow any wallet to send tips directly:
Copy receive() external payable {
emit Tipped(msg.sender, msg.value);
}
Withdraw all tips:
Copy function withdraw() external onlyOwner {
payable(owner).transfer(address(this).balance);
}
Example.sol
Copy // SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract STTTipJar {
address public owner;
event Tipped(address indexed from, uint256 amount);
event Withdrawn(address indexed to, uint256 amount);
constructor() {
owner = msg.sender;
}
receive() external payable {
emit Tipped(msg.sender, msg.value);
}
function withdraw() external {
require(msg.sender == owner, "Only owner can withdraw");
uint256 balance = address(this).balance;
require(balance > 0, "No tips available");
payable(owner).transfer(balance);
emit Withdrawn(owner, balance);
}
}
Frontend tip
Copy await walletClient.sendTransaction({
to: '0xTipJarAddress',
value: parseEther('0.05'),
});
Using a smart account + relayer (e.g. via Privy, Thirdweb), the dApp can cover gas fees:
Copy await sendTransaction({
to: contractAddress,
data: mintFunctionEncoded,
value: 0n, // user sends no STT
});
The Smart Contract function can execute mint or other logic as usual. The paymaster or relayer pays STT.
Conclusion
STT is native and used via msg.value
, .transfer()
, and payable
.
There is no contract address for STT .
You can integrate STT into any Solidity or Viem app with no ERC20 logic.
Account Abstraction enables gasless dApps using STT as sponsor currency.