See what your contract actually does.

Contract graphs and scenario tests

Tests: 6Findings: 5

Luora draws your contract as a graph of its functions, storage and calls, and runs the scenarios you wire on it as Foundry tests.

Open the Atlas
deposit100%
Function
caller · anyoneshares
amount : uint256totalShares
oracle.getSpotPrice
asset.transferFrom
Deposit
paused
withdraw▲1 H82%
Function
caller · anyoneshares
shareAmount : uint256totalShares
oracle.getSpotPrice
msg.sender.call{value}
Withdraw
paused
!shares
send failed
flashLoan▲1 H0%
Function
caller · anyoneasset.transfer
amount : uint256receiver.onFlashLoan
receiver : IFlashReceiver!repaid
data : bytes
shares[ ]
Storage slot
slot 5
written by deposit, withdraw, harvest
read by withdraw
totalShares
Storage slot
slot 4
written by deposit, withdraw, harvest
read by deposit
IOracle
External contract
called
· getSpotPrice()
IERC20 token
External contract
called
· transferFrom()
· transfer()
· approve()
Deposit
Event
emitted
user : address
assets : uint256
shares : uint256
msg.sender (caller)
External contract
called
· call()

Start from your own run,
not a blank file.

Graph

You can Run a scenario
with one click.

Actor · alice
Actor
name
roleuser
USDC
address
Call setOracle▲1 LRevert
Call
caller · owneroracle
newOracle : IOracleOracleUpdated
!owner
Expect revertPass
Expect revert
reason!owner
revertheld
AssertPass
Assert
checkonly owner can call setOracle
holds

Every call, event and cheatcode decoded with your own ABIs.

Wire actors and calls, export the scenario as a .t.sol.

Slither and Aderyn merged into one finding per issue.

How Luora works

Four layers,
one local run.

01234/ 04

Run your tests

Run forge test -vvvv and forge coverage in your Foundry project. One script, luora-export.mjs, folds both into a JSON file.

forge test -vvvvforge coverage
luora-data.jsonYour ABIs
ActorsCallsExpected reverts
SlitherAderynCoverage
luora-data.json
Decoded framesSource lines
Foundry test
FindingsUntested code

How Luora works

Four layers,
one local run.

  1. 01Run your tests

    Run forge test -vvvv and forge coverage in your Foundry project. One script, luora-export.mjs, folds both into a JSON file.

    forge test -vvvvforge coverageluora-data.json

  2. 02Read every frame

    Calls, events and cheatcodes decoded with your own ABIs. Each frame links to the source lines it executed.

    luora-data.jsonYour ABIsDecoded framesSource lines

  3. 03Write the test as a graph

    Wire actors, calls and expected reverts onto the contract. Run it in the browser, then export it as a Foundry test.

    ActorsCallsExpected revertsFoundry test

  4. 04Triage what is left

    Slither and Aderyn merged into one deduplicated list. Coverage shows the code no test ever touched.

    SlitherAderynCoverageFindingsUntested code

5 findings in the sample vault

Every analyzer,
one finding per issue.

Hover to read a finding

F-01 External call before state update. withdraw() calls out before burning shares and has no reentrancy guard.

6 forge tests traced in the sample run

Ask about the line,
not the whole file.

Every line of the contract belongs to a function, slot or call. Pick one and Luora answers about that piece: what it does, what to check, and a Foundry test that pins the safe behaviour.

Ask about a line…

 
ExplainWhat to checkWrite a test

The CLIs print text.Luora draws the contract.

What the CLIs printWhat Luora draws from it

Luora does not replace forge or the analyzers. It reads what they already produce and lays it over the contract.

  1. 01 / 03

    Traces you can read

    A text tree from forge -vvvv, the rest one opcode at a time in forge debug

    Every call, event and cheatcode decoded, each frame on the source lines and storage it touched, and a call graph per test.

  2. 02 / 03

    One finding per issue, triaged

    Two separate reports, no triage

    Slither and Aderyn merged into one finding per issue, triaged in place and exported as a Markdown report.

  3. 03 / 03

    Coverage and tests you can wire

    A per-file table from forge coverage, tests written by hand

    Coverage per function, untested ones first, and Lab scenarios exported as .t.sol tests.

FAQ

Answers to the questions auditors ask most.

How Luora runs, what it reads from your Foundry project and what stays on your machine.

Filter the questions
What does Luora need to run?

Node and Foundry. In your Foundry project, node luora-export.mjs runs forge test, decodes the traces with your own ABIs and writes luora-data.json; the app reads that file.

Where do Slither and Aderyn come in?

Optional. Point the exporter at their JSON reports (reports/slither.json and reports/aderyn.json by default, or --slither= and --aderyn=) and their results merge into the findings.

Does my code leave my machine?

The exporter and the app read local files. Triage status and notes are kept in your browser, per contract.

What does a Lab test check?

Intended behaviour. You wire actors, calls, expected reverts and asserts; a failing assertion in the exported .t.sol is a finding to look at, not an attack.

Can I re-run a single test?

Yes. node luora-export.mjs --mt test_x passes the filter through to forge, then reload the page.

Which contract does the atlas map?

One per export. Set LUORA_ATLAS=<Contract> to pick it when a project has several.

Not answered here?

Open an issue on the repository with the run and the contract you are looking at.

Open an issue

Open the sample vault.

Everything on this page runs on it. Then point Luora at your own Foundry project.

cd foundry && node luora-export.mjs