SOLIDITY Solidity source
AI-powered detection and analysis of Solidity source files.
Instant SOLIDITY File Detection
Use our advanced AI-powered tool to instantly detect and analyze Solidity source files with precision and speed.
File Information
Solidity source
Code
.sol
text/x-solidity
Solidity Smart Contract Language (.sol)
Solidity is a statically-typed programming language designed for developing smart contracts on the Ethereum blockchain and other Ethereum Virtual Machine (EVM) compatible networks. Created by Christian Reitwiessner, Alex Beregszaszi, and other Ethereum team members in 2014, Solidity is influenced by C++, Python, and JavaScript, making it accessible to developers with experience in these languages.
Technical Overview
Solidity is compiled to bytecode that runs on the Ethereum Virtual Machine (EVM). Smart contracts written in Solidity are immutable once deployed (unless designed with upgrade patterns) and can hold and transfer cryptocurrency, interact with other contracts, and maintain state on the blockchain. The language emphasizes security, gas efficiency, and formal verification.
Key Features
- Static Typing: Strong type system with compile-time checks
- Inheritance: Object-oriented programming with contract inheritance
- Libraries: Reusable code libraries for common functionality
- Modifiers: Function modifiers for access control and validation
- Events: Logging mechanism for off-chain applications
- Inline Assembly: Low-level EVM operations for optimization
Solidity Syntax and Structure
Basic Contract Structure
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
// Import statements
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
/**
* @title SimpleToken
* @dev A basic ERC20-compatible token contract
*/
contract SimpleToken is IERC20, Ownable, ReentrancyGuard {
// State variables
string public name;
string public symbol;
uint8 public decimals;
uint256 private _totalSupply;
// Mappings
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
// Events
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
event Mint(address indexed to, uint256 amount);
event Burn(address indexed from, uint256 amount);
// Modifiers
modifier validAddress(address _addr) {
require(_addr != address(0), "Invalid address");
_;
}
modifier sufficientBalance(address _from, uint256 _amount) {
require(_balances[_from] >= _amount, "Insufficient balance");
_;
}
// Constructor
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals,
uint256 _initialSupply
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
_totalSupply = _initialSupply * 10**_decimals;
_balances[msg.sender] = _totalSupply;
emit Transfer(address(0), msg.sender, _totalSupply);
}
// View functions
function totalSupply() external view override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) external view override returns (uint256) {
return _balances[account];
}
function allowance(address owner, address spender)
external
view
override
returns (uint256)
{
return _allowances[owner][spender];
}
// Public functions
function transfer(address to, uint256 amount)
external
override
validAddress(to)
sufficientBalance(msg.sender, amount)
returns (bool)
{
_transfer(msg.sender, to, amount);
return true;
}
function approve(address spender, uint256 amount)
external
override
validAddress(spender)
returns (bool)
{
_approve(msg.sender, spender, amount);
return true;
}
function transferFrom(address from, address to, uint256 amount)
external
override
validAddress(to)
sufficientBalance(from, amount)
returns (bool)
{
uint256 currentAllowance = _allowances[from][msg.sender];
require(currentAllowance >= amount, "Transfer amount exceeds allowance");
_transfer(from, to, amount);
_approve(from, msg.sender, currentAllowance - amount);
return true;
}
// Owner functions
function mint(address to, uint256 amount)
external
onlyOwner
validAddress(to)
{
_totalSupply += amount;
_balances[to] += amount;
emit Mint(to, amount);
emit Transfer(address(0), to, amount);
}
function burn(uint256 amount) external sufficientBalance(msg.sender, amount) {
_totalSupply -= amount;
_balances[msg.sender] -= amount;
emit Burn(msg.sender, amount);
emit Transfer(msg.sender, address(0), amount);
}
// Internal functions
function _transfer(address from, address to, uint256 amount) internal {
_balances[from] -= amount;
_balances[to] += amount;
emit Transfer(from, to, amount);
}
function _approve(address owner, address spender, uint256 amount) internal {
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
}
Advanced Contract Features
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
/**
* @title DecentralizedExchange
* @dev A simple decentralized exchange contract
*/
contract DecentralizedExchange is Pausable, ReentrancyGuard {
using SafeMath for uint256;
// Structs
struct Order {
uint256 id;
address trader;
address tokenAddress;
uint256 amount;
uint256 price;
bool isBuyOrder;
bool isActive;
uint256 timestamp;
}
struct TokenInfo {
string symbol;
address tokenAddress;
bool isListed;
uint256 minOrderAmount;
uint256 tradingFee; // in basis points (1 = 0.01%)
}
// State variables
uint256 public nextOrderId;
uint256 public platformFee = 30; // 0.3% in basis points
address public feeRecipient;
// Mappings
mapping(uint256 => Order) public orders;
mapping(address => TokenInfo) public listedTokens;
mapping(address => mapping(address => uint256)) public balances; // user => token => balance
mapping(address => uint256[]) public userOrders;
// Arrays
uint256[] public activeOrderIds;
address[] public tokenList;
// Events
event TokenListed(address indexed token, string symbol, uint256 minOrderAmount);
event OrderPlaced(
uint256 indexed orderId,
address indexed trader,
address indexed token,
uint256 amount,
uint256 price,
bool isBuyOrder
);
event OrderFilled(
uint256 indexed orderId,
address indexed buyer,
address indexed seller,
uint256 amount,
uint256 price
);
event OrderCancelled(uint256 indexed orderId, address indexed trader);
event Deposit(address indexed user, address indexed token, uint256 amount);
event Withdrawal(address indexed user, address indexed token, uint256 amount);
// Custom errors
error TokenNotListed(address token);
error InsufficientBalance(address user, address token, uint256 required, uint256 available);
error OrderNotFound(uint256 orderId);
error UnauthorizedAccess(address caller, address required);
error InvalidOrderAmount(uint256 amount, uint256 minimum);
constructor(address _feeRecipient) {
feeRecipient = _feeRecipient;
}
// Modifiers
modifier onlyListedToken(address token) {
if (!listedTokens[token].isListed) {
revert TokenNotListed(token);
}
_;
}
modifier validOrderAmount(address token, uint256 amount) {
uint256 minAmount = listedTokens[token].minOrderAmount;
if (amount < minAmount) {
revert InvalidOrderAmount(amount, minAmount);
}
_;
}
modifier orderExists(uint256 orderId) {
if (orders[orderId].trader == address(0)) {
revert OrderNotFound(orderId);
}
_;
}
modifier onlyOrderOwner(uint256 orderId) {
if (orders[orderId].trader != msg.sender) {
revert UnauthorizedAccess(msg.sender, orders[orderId].trader);
}
_;
}
// Admin functions
function listToken(
address tokenAddress,
string calldata symbol,
uint256 minOrderAmount
) external onlyOwner {
require(!listedTokens[tokenAddress].isListed, "Token already listed");
listedTokens[tokenAddress] = TokenInfo({
symbol: symbol,
tokenAddress: tokenAddress,
isListed: true,
minOrderAmount: minOrderAmount,
tradingFee: 0
});
tokenList.push(tokenAddress);
emit TokenListed(tokenAddress, symbol, minOrderAmount);
}
function updateTradingFee(address token, uint256 newFee) external onlyOwner {
require(newFee <= 1000, "Fee cannot exceed 10%"); // Max 10%
listedTokens[token].tradingFee = newFee;
}
function pause() external onlyOwner {
_pause();
}
function unpause() external onlyOwner {
_unpause();
}
// Deposit and withdrawal functions
function depositEther() external payable nonReentrant {
require(msg.value > 0, "Deposit amount must be positive");
balances[msg.sender][address(0)] = balances[msg.sender][address(0)].add(msg.value);
emit Deposit(msg.sender, address(0), msg.value);
}
function depositToken(address token, uint256 amount)
external
onlyListedToken(token)
nonReentrant
{
require(amount > 0, "Deposit amount must be positive");
IERC20(token).transferFrom(msg.sender, address(this), amount);
balances[msg.sender][token] = balances[msg.sender][token].add(amount);
emit Deposit(msg.sender, token, amount);
}
function withdrawEther(uint256 amount) external nonReentrant {
if (balances[msg.sender][address(0)] < amount) {
revert InsufficientBalance(
msg.sender,
address(0),
amount,
balances[msg.sender][address(0)]
);
}
balances[msg.sender][address(0)] = balances[msg.sender][address(0)].sub(amount);
payable(msg.sender).transfer(amount);
emit Withdrawal(msg.sender, address(0), amount);
}
function withdrawToken(address token, uint256 amount)
external
onlyListedToken(token)
nonReentrant
{
if (balances[msg.sender][token] < amount) {
revert InsufficientBalance(
msg.sender,
token,
amount,
balances[msg.sender][token]
);
}
balances[msg.sender][token] = balances[msg.sender][token].sub(amount);
IERC20(token).transfer(msg.sender, amount);
emit Withdrawal(msg.sender, token, amount);
}
// Trading functions
function placeOrder(
address token,
uint256 amount,
uint256 price,
bool isBuyOrder
)
external
onlyListedToken(token)
validOrderAmount(token, amount)
whenNotPaused
nonReentrant
returns (uint256 orderId)
{
// Check if user has sufficient balance
address paymentToken = isBuyOrder ? address(0) : token; // ETH for buy orders, token for sell orders
uint256 requiredAmount = isBuyOrder ? amount.mul(price) : amount;
if (balances[msg.sender][paymentToken] < requiredAmount) {
revert InsufficientBalance(
msg.sender,
paymentToken,
requiredAmount,
balances[msg.sender][paymentToken]
);
}
orderId = nextOrderId++;
orders[orderId] = Order({
id: orderId,
trader: msg.sender,
tokenAddress: token,
amount: amount,
price: price,
isBuyOrder: isBuyOrder,
isActive: true,
timestamp: block.timestamp
});
// Lock the funds
balances[msg.sender][paymentToken] = balances[msg.sender][paymentToken].sub(requiredAmount);
activeOrderIds.push(orderId);
userOrders[msg.sender].push(orderId);
emit OrderPlaced(orderId, msg.sender, token, amount, price, isBuyOrder);
// Try to match the order immediately
_matchOrder(orderId);
}
function cancelOrder(uint256 orderId)
external
orderExists(orderId)
onlyOrderOwner(orderId)
nonReentrant
{
Order storage order = orders[orderId];
require(order.isActive, "Order is not active");
order.isActive = false;
// Refund locked funds
address refundToken = order.isBuyOrder ? address(0) : order.tokenAddress;
uint256 refundAmount = order.isBuyOrder ? order.amount.mul(order.price) : order.amount;
balances[order.trader][refundToken] = balances[order.trader][refundToken].add(refundAmount);
_removeFromActiveOrders(orderId);
emit OrderCancelled(orderId, msg.sender);
}
// Internal functions
function _matchOrder(uint256 orderId) internal {
Order storage newOrder = orders[orderId];
for (uint256 i = 0; i < activeOrderIds.length; i++) {
uint256 existingOrderId = activeOrderIds[i];
Order storage existingOrder = orders[existingOrderId];
if (existingOrder.id == orderId || !existingOrder.isActive) continue;
if (existingOrder.tokenAddress != newOrder.tokenAddress) continue;
if (existingOrder.isBuyOrder == newOrder.isBuyOrder) continue;
// Check if orders can be matched
bool canMatch = newOrder.isBuyOrder ?
newOrder.price >= existingOrder.price :
newOrder.price <= existingOrder.price;
if (canMatch) {
_executeOrder(orderId, existingOrderId);
break;
}
}
}
function _executeOrder(uint256 buyOrderId, uint256 sellOrderId) internal {
Order storage buyOrder = orders[buyOrderId];
Order storage sellOrder = orders[sellOrderId];
// Determine execution price and amount
uint256 executionPrice = sellOrder.price; // Use sell order price
uint256 executionAmount = buyOrder.amount < sellOrder.amount ?
buyOrder.amount : sellOrder.amount;
// Calculate fees
uint256 tokenFee = listedTokens[buyOrder.tokenAddress].tradingFee;
uint256 buyerFee = executionAmount.mul(platformFee.add(tokenFee)).div(10000);
uint256 sellerFee = executionAmount.mul(executionPrice).mul(platformFee.add(tokenFee)).div(10000);
// Transfer tokens
balances[buyOrder.trader][buyOrder.tokenAddress] =
balances[buyOrder.trader][buyOrder.tokenAddress].add(executionAmount.sub(buyerFee));
balances[sellOrder.trader][address(0)] =
balances[sellOrder.trader][address(0)].add(executionAmount.mul(executionPrice).sub(sellerFee));
// Transfer fees
balances[feeRecipient][buyOrder.tokenAddress] =
balances[feeRecipient][buyOrder.tokenAddress].add(buyerFee);
balances[feeRecipient][address(0)] =
balances[feeRecipient][address(0)].add(sellerFee);
// Update order amounts
buyOrder.amount = buyOrder.amount.sub(executionAmount);
sellOrder.amount = sellOrder.amount.sub(executionAmount);
// Mark completed orders as inactive
if (buyOrder.amount == 0) {
buyOrder.isActive = false;
_removeFromActiveOrders(buyOrderId);
}
if (sellOrder.amount == 0) {
sellOrder.isActive = false;
_removeFromActiveOrders(sellOrderId);
}
emit OrderFilled(
buyOrderId,
buyOrder.trader,
sellOrder.trader,
executionAmount,
executionPrice
);
}
function _removeFromActiveOrders(uint256 orderId) internal {
for (uint256 i = 0; i < activeOrderIds.length; i++) {
if (activeOrderIds[i] == orderId) {
activeOrderIds[i] = activeOrderIds[activeOrderIds.length - 1];
activeOrderIds.pop();
break;
}
}
}
// View functions
function getActiveOrders() external view returns (uint256[] memory) {
return activeOrderIds;
}
function getUserOrders(address user) external view returns (uint256[] memory) {
return userOrders[user];
}
function getTokenList() external view returns (address[] memory) {
return tokenList;
}
function getOrderBook(address token)
external
view
returns (uint256[] memory buyOrders, uint256[] memory sellOrders)
{
uint256 buyCount = 0;
uint256 sellCount = 0;
// Count orders
for (uint256 i = 0; i < activeOrderIds.length; i++) {
Order storage order = orders[activeOrderIds[i]];
if (order.tokenAddress == token && order.isActive) {
if (order.isBuyOrder) {
buyCount++;
} else {
sellCount++;
}
}
}
// Populate arrays
buyOrders = new uint256[](buyCount);
sellOrders = new uint256[](sellCount);
uint256 buyIndex = 0;
uint256 sellIndex = 0;
for (uint256 i = 0; i < activeOrderIds.length; i++) {
Order storage order = orders[activeOrderIds[i]];
if (order.tokenAddress == token && order.isActive) {
if (order.isBuyOrder) {
buyOrders[buyIndex++] = order.id;
} else {
sellOrders[sellIndex++] = order.id;
}
}
}
}
}
Development Tools and Framework
Hardhat Development Environment
// hardhat.config.js
require("@nomicfoundation/hardhat-toolbox");
require("@openzeppelin/hardhat-upgrades");
require("hardhat-gas-reporter");
require("solidity-coverage");
module.exports = {
solidity: {
version: "0.8.19",
settings: {
optimizer: {
enabled: true,
runs: 200
}
}
},
networks: {
hardhat: {
chainId: 31337
},
sepolia: {
url: `https://sepolia.infura.io/v3/${process.env.INFURA_API_KEY}`,
accounts: [process.env.PRIVATE_KEY]
},
mainnet: {
url: `https://mainnet.infura.io/v3/${process.env.INFURA_API_KEY}`,
accounts: [process.env.PRIVATE_KEY]
}
},
gasReporter: {
enabled: process.env.REPORT_GAS !== undefined,
currency: "USD"
},
etherscan: {
apiKey: process.env.ETHERSCAN_API_KEY
}
};
Testing with Hardhat
// test/SimpleToken.test.js
const { expect } = require("chai");
const { ethers } = require("hardhat");
describe("SimpleToken", function () {
let token;
let owner;
let addr1;
let addr2;
beforeEach(async function () {
[owner, addr1, addr2] = await ethers.getSigners();
const SimpleToken = await ethers.getContractFactory("SimpleToken");
token = await SimpleToken.deploy(
"Test Token",
"TEST",
18,
1000000 // 1 million tokens
);
});
describe("Deployment", function () {
it("Should set the right owner", async function () {
expect(await token.owner()).to.equal(owner.address);
});
it("Should assign the total supply to the owner", async function () {
const ownerBalance = await token.balanceOf(owner.address);
expect(await token.totalSupply()).to.equal(ownerBalance);
});
it("Should set the correct token details", async function () {
expect(await token.name()).to.equal("Test Token");
expect(await token.symbol()).to.equal("TEST");
expect(await token.decimals()).to.equal(18);
});
});
describe("Transactions", function () {
it("Should transfer tokens between accounts", async function () {
await token.transfer(addr1.address, 50);
const addr1Balance = await token.balanceOf(addr1.address);
expect(addr1Balance).to.equal(50);
await token.connect(addr1).transfer(addr2.address, 50);
const addr2Balance = await token.balanceOf(addr2.address);
expect(addr2Balance).to.equal(50);
});
it("Should fail if sender doesn't have enough tokens", async function () {
const initialOwnerBalance = await token.balanceOf(owner.address);
await expect(
token.connect(addr1).transfer(owner.address, 1)
).to.be.revertedWith("Insufficient balance");
expect(await token.balanceOf(owner.address)).to.equal(initialOwnerBalance);
});
it("Should update balances after transfers", async function () {
const initialOwnerBalance = await token.balanceOf(owner.address);
await token.transfer(addr1.address, 100);
await token.transfer(addr2.address, 50);
const finalOwnerBalance = await token.balanceOf(owner.address);
expect(finalOwnerBalance).to.equal(initialOwnerBalance - 150);
const addr1Balance = await token.balanceOf(addr1.address);
expect(addr1Balance).to.equal(100);
const addr2Balance = await token.balanceOf(addr2.address);
expect(addr2Balance).to.equal(50);
});
});
describe("Allowances", function () {
it("Should approve and transfer from another account", async function () {
await token.approve(addr1.address, 100);
expect(await token.allowance(owner.address, addr1.address)).to.equal(100);
await token.connect(addr1).transferFrom(owner.address, addr2.address, 50);
expect(await token.balanceOf(addr2.address)).to.equal(50);
expect(await token.allowance(owner.address, addr1.address)).to.equal(50);
});
});
describe("Minting and Burning", function () {
it("Should allow owner to mint tokens", async function () {
const initialSupply = await token.totalSupply();
await token.mint(addr1.address, 1000);
expect(await token.balanceOf(addr1.address)).to.equal(1000);
expect(await token.totalSupply()).to.equal(initialSupply.add(1000));
});
it("Should allow users to burn their tokens", async function () {
await token.transfer(addr1.address, 1000);
const initialSupply = await token.totalSupply();
const initialBalance = await token.balanceOf(addr1.address);
await token.connect(addr1).burn(500);
expect(await token.balanceOf(addr1.address)).to.equal(initialBalance - 500);
expect(await token.totalSupply()).to.equal(initialSupply.sub(500));
});
});
});
Deployment Script
// scripts/deploy.js
const { ethers, upgrades } = require("hardhat");
async function main() {
const [deployer] = await ethers.getSigners();
console.log("Deploying contracts with the account:", deployer.address);
console.log("Account balance:", (await deployer.getBalance()).toString());
// Deploy SimpleToken
const SimpleToken = await ethers.getContractFactory("SimpleToken");
const token = await SimpleToken.deploy(
"MyToken",
"MTK",
18,
1000000 // 1 million tokens
);
await token.deployed();
console.log("SimpleToken deployed to:", token.address);
// Deploy DecentralizedExchange
const DecentralizedExchange = await ethers.getContractFactory("DecentralizedExchange");
const exchange = await DecentralizedExchange.deploy(deployer.address);
await exchange.deployed();
console.log("DecentralizedExchange deployed to:", exchange.address);
// List the token on the exchange
await exchange.listToken(token.address, "MTK", ethers.utils.parseEther("1"));
console.log("Token listed on exchange");
// Verify contracts on Etherscan
if (hre.network.name !== "hardhat") {
console.log("Waiting for block confirmations...");
await token.deployTransaction.wait(6);
await hre.run("verify:verify", {
address: token.address,
constructorArguments: ["MyToken", "MTK", 18, 1000000],
});
await hre.run("verify:verify", {
address: exchange.address,
constructorArguments: [deployer.address],
});
}
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
Security Best Practices
Common Vulnerabilities and Prevention
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
/**
* @title SecureContract
* @dev Example contract demonstrating security best practices
*/
contract SecureContract is ReentrancyGuard, Pausable, AccessControl {
// Use SafeMath for older Solidity versions (< 0.8.0)
// For 0.8.0+, arithmetic operations have built-in overflow protection
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
mapping(address => uint256) private balances;
uint256 private totalSupply;
// Events for transparency
event Deposit(address indexed user, uint256 amount);
event Withdrawal(address indexed user, uint256 amount);
constructor() {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(ADMIN_ROLE, msg.sender);
}
// Reentrancy protection
function withdraw(uint256 amount) external nonReentrant whenNotPaused {
require(balances[msg.sender] >= amount, "Insufficient balance");
// Update state before external call (Checks-Effects-Interactions pattern)
balances[msg.sender] -= amount;
// External call last
(bool success, ) = payable(msg.sender).call{value: amount}("");
require(success, "Transfer failed");
emit Withdrawal(msg.sender, amount);
}
// Access control
function emergencyPause() external onlyRole(ADMIN_ROLE) {
_pause();
}
function emergencyUnpause() external onlyRole(ADMIN_ROLE) {
_unpause();
}
// Input validation
function transfer(address to, uint256 amount) external {
require(to != address(0), "Cannot transfer to zero address");
require(to != address(this), "Cannot transfer to contract");
require(amount > 0, "Amount must be positive");
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount;
balances[to] += amount;
}
// Gas optimization: pack structs efficiently
struct User {
uint128 balance; // Instead of uint256 if range is sufficient
uint64 lastUpdate; // timestamp
uint32 level; // user level
bool isActive; // boolean
// Total: 32 bytes (1 slot)
}
// Use custom errors (more gas efficient than require strings)
error InsufficientFunds(uint256 requested, uint256 available);
error UnauthorizedAccess(address caller);
error InvalidInput(string reason);
function optimizedWithdraw(uint256 amount) external {
if (balances[msg.sender] < amount) {
revert InsufficientFunds(amount, balances[msg.sender]);
}
// ... rest of function
}
// Price oracle protection (prevent flash loan attacks)
mapping(uint256 => uint256) private priceHistory;
uint256 private constant PRICE_TOLERANCE = 100; // 1%
function updatePrice(uint256 newPrice) external onlyRole(ADMIN_ROLE) {
uint256 currentPrice = priceHistory[block.number - 1];
if (currentPrice > 0) {
uint256 priceChange = newPrice > currentPrice ?
newPrice - currentPrice : currentPrice - newPrice;
require(
priceChange * 10000 / currentPrice <= PRICE_TOLERANCE,
"Price change too large"
);
}
priceHistory[block.number] = newPrice;
}
// Front-running protection with commit-reveal scheme
mapping(address => bytes32) private commitments;
mapping(address => uint256) private commitBlocks;
function commitAction(bytes32 commitment) external {
commitments[msg.sender] = commitment;
commitBlocks[msg.sender] = block.number;
}
function revealAction(uint256 nonce, uint256 action) external {
require(
block.number > commitBlocks[msg.sender] + 1,
"Must wait at least one block"
);
require(
keccak256(abi.encodePacked(nonce, action, msg.sender)) == commitments[msg.sender],
"Invalid reveal"
);
// Execute action
delete commitments[msg.sender];
delete commitBlocks[msg.sender];
}
}
File Format Details
- MIME Type:
text/x-solidity
- File Extension:
.sol
- Character Encoding: UTF-8
- Compiler: solc (Solidity Compiler)
- Target: Ethereum Virtual Machine (EVM)
Solidity provides the foundation for decentralized applications and smart contracts on Ethereum and compatible blockchains. Its focus on security, gas efficiency, and formal verification makes it essential for building reliable and trustworthy blockchain applications. The language continues to evolve with new features and security improvements to support the growing DeFi and Web3 ecosystem.
AI-Powered SOLIDITY File Analysis
Instant Detection
Quickly identify Solidity source files with high accuracy using Google's advanced Magika AI technology.
Security Analysis
Analyze file structure and metadata to ensure the file is legitimate and safe to use.
Detailed Information
Get comprehensive details about file type, MIME type, and other technical specifications.
Privacy First
All analysis happens in your browser - no files are uploaded to our servers.
Related File Types
Explore other file types in the Code category and discover more formats:
Start Analyzing SOLIDITY Files Now
Use our free AI-powered tool to detect and analyze Solidity source files instantly with Google's Magika technology.
⚡ Try File Detection Tool