OMEGA Best Practices
Guidelines for writing secure, efficient, and maintainable OMEGA smart contracts
Security Best Practices
Input Validation
Always validate inputs to prevent unexpected behavior:
function transfer(address to, uint256 amount) public returns (bool) {
require(to != address(0), "Invalid recipient address");
require(amount > 0, "Amount must be positive");
require(balances[msg.sender] >= amount, "Insufficient balance");
// Function logic here
}
Reentrancy Protection
Use the checks-effects-interactions pattern:
function withdraw(uint256 amount) public {
// Checks
require(balances[msg.sender] >= amount, "Insufficient balance");
// Effects
balances[msg.sender] -= amount;
// Interactions
payable(msg.sender).transfer(amount);
}
Access Control
blockchain SecureContract {
state {
address owner;
mapping(address => bool) admins;
}
modifier only_owner() {
require(msg.sender == owner, "Only owner can call this");
_;
}
modifier only_admin() {
require(admins[msg.sender], "Only admin can call this");
_;
}
function set_admin(address admin, bool status) public only_owner {
admins[admin] = status;
}
}
Gas Optimization
Use Appropriate Data Types
// Good: Use smaller types when possible
uint8 small_number;
uint32 medium_number;
// Avoid: Using uint256 for small values unnecessarily
uint256 tiny_flag; // Wasteful for boolean-like values
Pack Struct Variables
// Good: Packed struct (saves gas)
struct User {
uint128 balance; // 16 bytes
uint64 timestamp; // 8 bytes
uint32 id; // 4 bytes
uint32 status; // 4 bytes
// Total: 32 bytes (1 storage slot)
}
// Avoid: Unpacked struct
struct BadUser {
uint256 balance; // 32 bytes
uint256 timestamp; // 32 bytes
uint256 id; // 32 bytes
// Total: 96 bytes (3 storage slots)
}
Batch Operations
function batch_transfer(address[] recipients, uint256[] amounts) public {
require(recipients.length == amounts.length, "Array length mismatch");
for (uint256 i = 0; i < recipients.length; i++) {
transfer(recipients[i], amounts[i]);
}
}
Code Organization
Use Meaningful Names
// Good
function calculate_compound_interest(uint256 principal, uint256 rate, uint256 time)
public pure returns (uint256) {
// Implementation
}
// Avoid
function calc(uint256 p, uint256 r, uint256 t) public pure returns (uint256) {
// Implementation
}
Modular Design
// Separate concerns into different contracts
blockchain TokenLogic {
// Core token functionality
}
blockchain TokenGovernance {
// Governance-related functions
}
blockchain TokenVesting {
// Vesting and time-locked functions
}
Documentation
/// @title ERC20 Token Implementation
/// @author Your Name
/// @notice This contract implements a basic ERC20 token
/// @dev All function calls are currently implemented without side effects
blockchain MyToken {
/// @notice Transfer tokens to a specified address
/// @param to The address to transfer to
/// @param amount The amount to be transferred
/// @return success True if the transfer was successful
function transfer(address to, uint256 amount) public returns (bool success) {
// Implementation
}
}
Cross-Chain Best Practices
Handle Network Differences
function get_network_specific_data() public view returns (uint256) {
#[target(evm)]
return block.number;
#[target(solana)]
return Clock::get().slot;
#[target(cosmos)]
return env.block.height;
}
Cross-Chain Communication
@cross_chain(target = "solana")
function bridge_tokens(bytes32 solana_recipient, uint256 amount) public {
require(amount > 0, "Amount must be positive");
require(balances[msg.sender] >= amount, "Insufficient balance");
// Lock tokens on source chain
balances[msg.sender] -= amount;
locked_balances += amount;
// Emit cross-chain event
emit CrossChainTransfer(msg.sender, solana_recipient, amount, "solana");
}
Testing Best Practices
Comprehensive Test Coverage
// Test file: tests/token_tests.omega
test "should transfer tokens correctly" {
let token = deploy_token("Test", "TST", 1000);
let result = token.transfer(user1, 100);
assert(result == true);
assert(token.balance_of(user1) == 100);
assert(token.balance_of(deployer) == 900);
}
test "should fail transfer with insufficient balance" {
let token = deploy_token("Test", "TST", 100);
expect_revert(
token.transfer(user1, 200),
"Insufficient balance"
);
}
Edge Case Testing
test "should handle zero transfers" {
let token = deploy_token("Test", "TST", 1000);
let result = token.transfer(user1, 0);
// Define expected behavior for zero transfers
assert(result == false); // or true, depending on design
}
test "should handle maximum values" {
let token = deploy_token("Test", "TST", type(uint256).max);
// Test behavior with maximum possible values
}
Performance Optimization
Minimize Storage Operations
// Good: Single storage write
function update_user_data(uint256 new_balance, uint256 new_timestamp) public {
UserData storage user = users[msg.sender];
user.balance = new_balance;
user.last_update = new_timestamp;
}
// Avoid: Multiple storage operations
function bad_update_user_data(uint256 new_balance, uint256 new_timestamp) public {
users[msg.sender].balance = new_balance; // Storage write 1
users[msg.sender].last_update = new_timestamp; // Storage write 2
}
Use Events for Data Storage
// Use events for historical data that doesn't need to be queried on-chain
event UserAction(
address indexed user,
string action_type,
uint256 timestamp,
bytes data
);
function perform_action(string action_type, bytes data) public {
// Minimal on-chain storage
user_action_count[msg.sender]++;
// Detailed data in events
emit UserAction(msg.sender, action_type, block.timestamp, data);
}
Deployment Best Practices
Environment Configuration
# omega.toml
[deployment.testnet]
gas_limit = 8000000
gas_price = "20 gwei"
confirmations = 2
[deployment.mainnet]
gas_limit = 6000000
gas_price = "auto"
confirmations = 5
Gradual Rollout
- Deploy to testnet first
- Conduct thorough testing
- Deploy to mainnet with limited functionality
- Gradually enable full features
Common Pitfalls to Avoid
⚠️ Integer Overflow/Underflow
Always use safe math operations or built-in overflow checks.
⚠️ Uninitialized Storage
Initialize all state variables properly in the constructor.
⚠️ Gas Limit Issues
Be aware of gas limits when processing arrays or loops.
⚠️ Front-Running
Consider commit-reveal schemes for sensitive operations.