A user wants to interact with a decentralized exchange contract on Ethereum, deposit collateral into a lending protocol, or mint an NFT from a smart contract. Before sending the transaction, that user faces a critical blind spot: the wallet displays a destination address, a gas estimate, and a description like « Approve Token, » but the actual code being executed remains opaque. The signed transaction will trigger bytecode execution on the blockchain, potentially transferring funds, granting permissions, or executing logic that the user cannot inspect in real time. This is where transaction simulation enters the picture as a practical defense mechanism.
Rabby Wallet’s transaction simulation system attempts to bridge that gap by executing the contract interaction off-chain, analyzing the results, and alerting the user before the transaction is signed and broadcast. The system does not make the underlying contract code transparent or prevent every possible exploit, but it does create a layer of analysis that catches common mistakes, phishing attempts, and unintended consequences. Understanding how this simulation works at the code level reveals both its power and its limitations.

What transaction simulation actually executes
When a user approves a contract interaction in Rabby, the wallet does not submit the transaction to the blockchain immediately. Instead, it sends a request to an Ethereum node—typically via the Infura, Alchemy, or another JSON-RPC provider—asking the node to execute the transaction in a simulated environment. This simulated execution is called a dry-run or call. The node processes the bytecode, state changes, storage writes, and internal function calls exactly as it would during a real transaction, but the results are not persisted to the blockchain. The state reverts when the simulation completes.
For a token swap on Uniswap, for example, the simulation executes the `swap` or `swapExactTokensForTokens` function, computing the output amount based on current liquidity pools, slippage, and the contract’s internal logic. The wallet can then display the expected output tokens, not just a generic « swap » label. For an NFT mint, the simulation runs the `mint` function, checking whether the user has sufficient funds, whether the contract is accepting new mints, and whether any special conditions (whitelist, time limits, price logic) apply.
The simulation operates within a constrained environment. The node uses the current blockchain state—the latest block’s account balances, storage values, and contract bytecode—and executes the transaction as it would in a real block. However, the simulation does not account for future state changes. If a liquidity pool’s state shifts between the simulation and actual execution, or if another transaction ahead in the mempool alters the state, the actual result can differ significantly. This is why Rabby also displays slippage tolerance and deadline parameters for DeFi transactions: these are the user’s explicit limits to handle that uncertainty.
The code path involved in simulation is the contract’s fallback function or designated entry point, plus any internal function calls it triggers. A complex token swap may call multiple contracts—a router, the Uniswap factory, liquidity pools, and token contracts—all within a single simulated transaction. The simulation traces all of these interactions, collecting data about token transfers, approval changes, and balance shifts. This is far more informative than displaying only the direct address and value sent.
How Rabby parses contract output and state changes
After the simulation completes, Rabby must interpret what happened. The Ethereum node returns several pieces of information: the transaction’s status (success or revert), the output data, gas used, and a detailed log of all events emitted during execution. Events are structured logs that smart contracts emit to signal important state changes. A token transfer emits a `Transfer` event, an approval emits an `Approval` event, and a swap emits events specific to the exchange.
Rabby’s security layer parses these events to understand what the transaction actually does. If a user submits a transaction to a contract that purports to be a token, but the simulation reveals no token transfer events and instead shows a large outbound ETH transfer, the wallet can flag a mismatch between the user’s intent and the contract’s behavior. This is a common phishing pattern: a user is shown a clean interface prompting them to « approve, » but the actual contract drains their account.
The wallet also decodes the function call itself. Every transaction contains encoded data that specifies which function to call and what parameters to pass. Rabby decodes this data using the contract’s Application Binary Interface (ABI), a JSON specification that describes the contract’s public functions and their signatures. For a token’s `approve` function, the ABI specifies that the function takes two parameters: a `spender` address and an `amount`. Decoding the transaction data reveals which address is being approved and for how much. This decoded information is then displayed in human-readable form.
For more complex contracts, the parsing becomes more sophisticated. A multi-step transaction that calls a router contract, which in turn calls multiple liquidity pools and token contracts, generates many events. Rabby must correlate these events to understand the net effect: how many tokens in, how many tokens out, which addresses participated. The wallet builds a model of the transaction’s intended outcome and compares it against what the user is approving. If the approved transaction appears to transfer the user’s funds to an unexpected address or amount, an alert appears.
Decoding approval transactions and permission risks
Token approvals are the most commonly simulated transaction type because they are the most commonly exploited. An ERC-20 token approval grants another address the right to transfer tokens on the user’s behalf, up to a specified amount. The code involved is a single line in most token contracts: a state variable that tracks allowances in the mapping `mapping(address => mapping(address => uint256)) allowances`.
When a user approves an amount, the contract updates this allowance. A user approving 1000 USDC to a Uniswap router is saying « the router can now transfer up to 1000 USDC from my account. » The simulation for an approval transaction typically shows no token movement—approvals do not transfer tokens, they grant permission. But Rabby can decode the approval parameters and alert the user if the approved amount is unlimited (uint256 max value) or if the spender address does not match the expected contract.
A refined security check flags approvals to newly created contracts or lesser-known addresses. This catches a class of attacks where a phishing site or compromised interface tricks a user into approving an attacker’s contract, which then drains the user’s token balance. Because the approval grants a fixed permission and the actual transfer happens later, the user may not realize the vulnerability until funds are gone. Rabby Wallet mitigates this by making the approval target explicit and flagging unusual amounts or addresses.
The simulation also helps detect approval transactions that are unusual in other ways. Some phishing contracts mimic legitimate ones but deploy their own token contract with a similar symbol. A simulation reveals that « approving USDC » is actually approving an ERC-20 token at an unexpected address. The decoded token address can be cross-checked against a known-good list, either maintained locally or fetched from a security service. This is not bulletproof—attackers can register similar addresses on block explorers—but it raises the bar for casual phishing.
Tracing DeFi interactions and slippage protection
A Uniswap V3 swap transaction is more complex than a simple approval. The user specifies an input token, output token, amount in, and minimum amount out. The contract router calculates a path through liquidity pools, executes multiple swaps if necessary, and returns the output. The simulation executes this entire path and reports the actual output amount.
Rabby’s display of the output amount is derived from the simulation. Instead of showing only « you are swapping 1 ETH, » the wallet shows « you are swapping 1 ETH for approximately 1500 USDC at current rates. » This figure comes from running the swap logic against the current state of the liquidity pools. If the user has set a slippage tolerance of 0.5%, the wallet computes the minimum output as 1500 × 0.995 = 1492.5 USDC and checks that the transaction includes this minimum as a parameter.
The simulation also reveals multi-hop swaps. If the user wants to swap an obscure token for another obscure token, the router may need to swap through ETH or USDC as intermediate steps. The simulation shows the full path: Token A → ETH → USDC → Token B. Each hop has its own slippage and price impact. Rabby aggregates this information to show the user the complete picture before signing.
Gas estimation is another output of simulation. The wallet can display the predicted gas cost based on the simulated execution. If the simulation shows that the transaction will use 150,000 gas units, and gas is priced at 50 gwei, the wallet calculates a total cost of 0.0075 ETH. This is more accurate than a blank estimate, though it can still change if network congestion shifts between simulation and actual execution.
Risk detection and alert mechanisms
The simulation generates a wealth of data, but displaying all of it would overwhelm most users. Rabby therefore applies a risk assessment layer on top of the simulation results. This layer checks for patterns that indicate phishing, permission abuse, or unintended consequences.
One check flags sudden balance changes. If the user is approving what appears to be a standard token swap, but the simulation shows the user’s account losing 10 ETH to an unknown address, the risk score increases. This can catch transactions that call multiple contracts in sequence, with one of them siphoning funds. Another check flags unexpected contract calls. If a user is swapping tokens on Uniswap but the transaction also calls a contract known to be used in exploits or rug pulls, an alert appears.
The risk detection system maintains a database of known malicious addresses, suspicious contract creation timestamps, and patterns associated with attacks. A newly created contract that claims to be a token but has no verified source code is higher risk than an Etherscan-verified contract used by thousands of users. Rabby uses these signals to categorize transactions as high, medium, or low risk. A high-risk transaction is not necessarily blocked, but the user sees a clear warning and must explicitly acknowledge the risk before proceeding.
False positives are a constant concern. A legitimate but uncommon transaction—such as an experimental DeFi protocol or a private transaction—may trigger alerts unnecessarily. Rabby attempts to calibrate its detection to catch genuine threats while remaining usable. Users who understand the underlying transaction can override warnings, but the design biases toward caution rather than hiding risk behind a clean interface.
Limitations and failure modes of simulation
Transaction simulation is powerful but not infallible. The simulation operates on the current blockchain state at the time of simulation. If the user delays signing, or if the mempool contains many pending transactions, the actual state when the transaction executes may differ. A liquidity pool’s price may have shifted, making the simulated output inaccurate. A contract may have changed ownership or been disabled. Simulation cannot predict the future.
Flash loan attacks illustrate a deeper limitation. A contract can borrow a large amount of tokens within a single transaction, use those tokens to manipulate prices, and repay the loan—all within one simulated execution. The simulation sees the state as if the attacker already has the funds, allowing the attack to appear legitimate. A user might approve a transaction that looks safe in simulation but participates in a flash loan attack once broadcast. Detecting this requires understanding the contract’s code, not just its outputs.
Simulation also depends on the completeness and accuracy of contract ABIs. If a contract’s function signature is not known, or if the ABI is incorrect, Rabby cannot decode the transaction data. The transaction appears as opaque bytecode, and the wallet displays a generic warning. This is safer than silently proceeding, but it also means users of new or obscure protocols cannot benefit from rich simulation data.
Finally, simulation cannot verify the user’s intent. The wallet can confirm that a transaction does what its code says it does, but not whether that outcome is what the user actually wants. A user might intend to swap 1 ETH but fat-finger the amount field and attempt to swap 10 ETH. The simulation correctly executes the 10 ETH swap, and the wallet displays the correct output. The risk check does not flag this because the transaction is technically valid and the amount field matches the user’s input. Verification of intent remains the user’s responsibility.
Comparison with other DeFi wallets and security approaches
MetaMask, the most widely deployed Ethereum wallet, has added transaction simulation and contract warnings in recent versions, but adoption is gradual and defaults are not always enabled. Ledger’s hardware wallet can display transaction details on a small screen, but parsing contract calls on a device with limited resources remains challenging. Trezor offers similar contract awareness through its firmware, focusing on high-risk operations like approvals and balance transfers.
Rabby’s approach is particularly strong for browser-based interactions because the wallet operates in an environment where it can easily integrate with web3 applications. When a user clicks « connect wallet » on a DeFi site, Rabby can inject itself into the transaction flow and intercept requests before they are signed. This is cleaner than a user manually copying a contract address and pasting it into a wallet.
However, Rabby’s security is ultimately limited by the browser environment. An attacker who compromises the browser, injects malicious JavaScript, or spoofs the wallet’s interface can potentially trick the user into signing dangerous transactions. Hardware wallets offer stronger isolation because the signing device is disconnected from the internet, making remote code injection impossible. Rabby is best suited for users who understand the risks of browser-based wallets and use it for moderate amounts rather than critical funds.
The blockchain security community continues to develop better simulation and alerting mechanisms. Tools like Tenderly and Etherscan’s simulation systems offer similar functionality for developers and advanced users. Integration of these services into wallets is the natural next step, and Rabby’s open-source architecture allows for community contributions and audits of its security logic.
Setting realistic expectations for transaction security
Transaction simulation is a powerful defensive tool, but users should understand what it protects against and what it does not. Simulation catches obvious phishing contracts, permission abuse, and unintended large transfers. It does not prevent sophisticated smart contract exploits, flash loan attacks, or attacks that execute over multiple transactions. It does not recover funds already sent to wrong addresses or stolen in prior transactions.
The correct mental model is that blockchain security is multi-layered. Transaction simulation is one layer. Hardware wallet isolation is another. Blockchain security audits of the protocols you use provide another. Limiting exposure by not holding large amounts in browser wallets is yet another. Together, these layers reduce risk to a manageable level.
Users should treat Rabby’s risk alerts as a starting signal, not a final verdict. A high-risk warning deserves investigation: researching the contract, checking its creation date and source code, and understanding what it claims to do. A low-risk transaction is not guaranteed to be safe; it simply means the simulation did not detect obvious problems. Risk assessment in decentralized finance is ultimately the user’s responsibility. The wallet can inform better decisions, but it cannot make decisions on behalf of the user.
Frequently asked questions
Does Rabby’s transaction simulation actually run the contract code?
Yes. Rabby sends a simulated transaction to an Ethereum node, which executes the contract code in a read-only environment. The node processes all state changes, internal function calls, and events exactly as it would in a real transaction, but the state is reverted when the simulation completes. This allows Rabby to determine what the transaction will do before the user signs it.
Can transaction simulation detect all phishing attacks and exploits?
No. Simulation catches obvious phishing patterns like unexpected balance transfers to unknown addresses, but it cannot detect sophisticated smart contract logic exploits, flash loan attacks, or attacks that span multiple transactions. Simulation shows what the contract does, not whether that outcome is harmful in every possible scenario. Users should treat simulation as one layer of defense, not the only one.
What happens if the simulated output differs from the actual transaction result?
State changes, mempool congestion, and time delays between simulation and execution can cause differences. Liquidity pools, oracle prices, and contract states can shift. This is why Rabby displays slippage tolerance parameters and deadlines for DeFi transactions. These limits allow the contract to revert the transaction if conditions change too much, protecting the user from severely unfavorable outcomes.