Skip to content

Solidity to Syscall Mapping

Back to Syscalls

Automatic Lowering

The compiler automatically translates standard Solidity constructs to the corresponding NeoVM syscalls. No manual syscall invocation is needed for these patterns.

For a shorter reader guide that separates runtime calls from devpack usage, see Syscalls and Devpack.

Mapping Table

Solidity ConstructSyscall / Neo CallNotes
msg.senderSystem.Runtime.GetCallingScriptHashReturns caller's script hash (UInt160)
address(this)System.Runtime.GetExecutingScriptHashReturns current contract's script hash
block.timestampSystem.Runtime.GetTimeMilliseconds, normalized to seconds
block.numberLedger.currentIndex (native call)Not a syscall — uses System.Contract.Call
gasleft()System.Runtime.GasLeftRemaining GAS in current invocation
State variable readSystem.Storage.GetKey derived from variable name via SHA256
State variable writeSystem.Storage.PutKey derived from variable name via SHA256
mapping[key] readSystem.Storage.GetKey = SHA256(serialize(key) || slot)
mapping[key] writeSystem.Storage.PutSame derived key
emit Event(...)System.Runtime.NotifyEvent name + args as notification
require(Runtime.checkWitness(addr))System.Runtime.CheckWitnessWitness verification (200 GAS)
address(target).call(...)System.Contract.CallCross-contract invocation (10 GAS)
address(target).staticcall(...)System.Contract.Call (read-only flags)Read-only cross-contract call
keccak256(...)CryptoLib.keccak256 (native call)Via System.Contract.Call, not a syscall
sha256(...)CryptoLib.sha256 (native call)Via System.Contract.Call, not a syscall

Example Lowering

solidity
// What you write:
contract Example {
    mapping(address => uint256) public balances;
    event Transfer(address indexed from, address indexed to, uint256 amount);

    function transfer(address to, uint256 amount) external {
        require(Runtime.checkWitness(msg.sender), "unauthorized");
        balances[msg.sender] -= amount;
        balances[to] += amount;
        emit Transfer(msg.sender, to, amount);
    }
}

// What the compiler emits (pseudocode):
// 1. System.Runtime.CheckWitness(callingScriptHash)  — 200 GAS
// 2. System.Storage.GetContext()                      — 1 GAS
// 3. System.Storage.Get(ctx, derived_key_sender)      — 100 GAS
// 4. System.Storage.Put(ctx, derived_key_sender, new) — 1,000 GAS
// 5. System.Storage.Get(ctx, derived_key_to)          — 100 GAS
// 6. System.Storage.Put(ctx, derived_key_to, new)     — 1,000 GAS
// 7. System.Runtime.Notify("Transfer", [from, to, amount]) — 1 GAS
// Total: ~2,402 GAS units (syscalls only, excludes opcode costs)

MIT Licensed