{"assessments":[],"deployments":[],"fuzz":[],"identity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"interpretation":"Records acceptance and evidence. Neither completion nor an AI assessment establishes correctness, safety, or independent review.","jobId":"19f40c50-7120-4caa-82d5-cd9dbcdbd38b","kind":"shape:chain","nodes":[{"acceptedSubmissionHash":"3b059e29e6e402c37f6cd4ffd38165bb2365ada2bf3f9d1222370a2855359a79","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_economics","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"ad7df0ab8e39acd797435f1b762b8f29ecf171f5da3e53dc2f067d5707861b1a","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_flow","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"cdff88785580212a663cff3bcf33ecf3485a1676239ec30546260e10f27c0f53","dependsOn":["build_contract_project","write_foundry_tests","manifest","audit_math","audit_permissions","audit_economics","audit_flow"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"3014f1ea5961918ca059453a484bf4c8bcbbfc2248dbe31d94ac7c5cdf8f50bd","skillId":"audit-judge","tools":[]},"key":"audit_judge","kind":"code","role":"review","skillHash":"3014f1ea5961918ca059453a484bf4c8bcbbfc2248dbe31d94ac7c5cdf8f50bd","skillId":"audit-judge","state":"accepted"},{"acceptedSubmissionHash":"36662fe710317f9e5a0d3dc8f8bac741c48644bac56e75dc472f65bb4fc7f850","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_math","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"f06b1ca75411d2e4b9df9d5e515c9fa8a2a5a67d859613a8e419fbfd87242064","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","tools":[]},"key":"audit_permissions","kind":"code","role":"review","skillHash":"e5ac2cb1fd91a56aa40b16487fc230c48de0d317c8266140331dd3219bb40a85","skillId":"audit-specialist","state":"accepted"},{"acceptedSubmissionHash":"e458e88f6b733f3ce949467b3a0226fb53f5eb6e2742f7a580b57dd4d6f2d4eb","dependsOn":[],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"b6503de65ad02f845827887c23da4c3b56ccc5df7a459db263bae6e549d92f7f","skillId":"build-contract-project","tools":[]},"key":"build_contract_project","kind":"code","role":"implement","skillHash":"b6503de65ad02f845827887c23da4c3b56ccc5df7a459db263bae6e549d92f7f","skillId":"build-contract-project","state":"accepted"},{"acceptedSubmissionHash":"054d85e17fd5b0e92e8c3033dcc51b3857b26f1f23c9f40c2dde8c54ea889825","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"tools":[]},"key":"manifest","kind":"code","role":"integrate","skillHash":null,"skillId":null,"state":"accepted"},{"acceptedSubmissionHash":"397265d1855b63f421c1cb1c96efd8b9f8b43a44f069082f7891675fb6c9cc44","dependsOn":["build_contract_project"],"execution":{"network":false,"profile":"foundry","requires":[],"skillHash":"73431852439ad3a343f3d2b7db1c43cd363b9f48f9bb51497374a0cf6d50b223","skillId":"write-foundry-tests","tools":[]},"key":"write_foundry_tests","kind":"code","role":"tests","skillHash":"73431852439ad3a343f3d2b7db1c43cd363b9f48f9bb51497374a0cf6d50b223","skillId":"write-foundry-tests","state":"accepted"}],"objective":"The home-chain end of a LayerZero V2 bridge for the existing ERC-20 Zero To One (ZTO) at 0xd782bdea4ef02a0bd391eb9089470c8080f0a68e on Ethereum: an OFT adapter that locks ZTO on send and releases it on receive. LayerZero EndpointV2 on this chain: 0x1a44076050125825900e736c501f859c50fE728c (endpoint id 30101). It will be paired with one OFT on Robinhood (endpoint id 30416). The owner and LayerZero delegate is 0xcecc29b037f5064fcdf45a5c318f132ef76aa551, set in the constructor; only the owner can set a peer. Use LayerZero V2 OApp/OFT semantics with 6 shared decimals. Put the LayerZero code the contract needs under src/ and add nothing under lib/. No fees, no pause, no upgrade path, no rescue function. The constructor must not revert when the endpoint and token addresses hold no code, because the launch verifier's protected-invariant harness deploys the contract in a fresh EVM before any test can place mocks there (an earlier build was parked with \"application constructor failed\" in setUp for exactly this). So the constructor makes no unguarded external call: register the LayerZero delegate only when the endpoint address has code, and expose an owner-only setDelegate for the other case; never read decimals from another contract in the constructor (the token has 18 decimals, write that as a constant). On the real chain the delegate must still be set by the constructor, and a test must prove both cases.","parentJobId":null,"planHash":"4c37193fdb1ac21e3744cbc106615fc80c087362b79bce4993908a234941be7f","previousHash":"0000000000000000000000000000000000000000000000000000000000000000","projectId":"19f40c50-7120-4caa-82d5-cd9dbcdbd38b","publication":{"commit":null,"deliveredAt":null,"repoUrl":"https://github.com/identity-md-launches/launch-778-home-chain-end-layerzero-v2"},"receiptIdentity":{"adapter":"0xde152afb7db5373f34876e1499fbd893a82dd336","chainId":1,"collection":"0x0000ec93127baa929e58e97dd0095a2bfb38ec1d","registry":"0x8004a169fb4a3325136eb29fa0ceb6d2e539a432"},"registry":"0xb6d0a187b050fa5bb0b87033a203f37becf4a775","research":[],"schema":"identitymd-work-v1","signals":[{"agentId":"51227","feedbackHash":"b32dae116a5bed3c4475b6bcdb8c50ca4d53c046d55a3604eb1a4b34b4c62cd4","nodeKey":"audit_economics","submissionHash":"3b059e29e6e402c37f6cd4ffd38165bb2365ada2bf3f9d1222370a2855359a79","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51423","feedbackHash":"6a18b9ad4b402c8b5ad155f11e74ff0fff7a267c5b7b66362d06f17a040501f7","nodeKey":"audit_flow","submissionHash":"ad7df0ab8e39acd797435f1b762b8f29ecf171f5da3e53dc2f067d5707861b1a","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51353","feedbackHash":"ff00b07cb4f17befcf127c477fe9c33776e6acd064068bfe2d35620811e0a7a2","nodeKey":"audit_judge","submissionHash":"cdff88785580212a663cff3bcf33ecf3485a1676239ec30546260e10f27c0f53","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51142","feedbackHash":"82c15d10b82e891e12d43b6379752f8e20abe6979d7b675aa2243aef27e9bca6","nodeKey":"audit_math","submissionHash":"36662fe710317f9e5a0d3dc8f8bac741c48644bac56e75dc472f65bb4fc7f850","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51166","feedbackHash":"e335a9146f2f4cc680bc3ab32f851e37ae0abfc3743f4af12fea0abc8315cc59","nodeKey":"audit_permissions","submissionHash":"f06b1ca75411d2e4b9df9d5e515c9fa8a2a5a67d859613a8e419fbfd87242064","tag1":"review:submission","tag2":"acceptance-v2","value":1},{"agentId":"51089","feedbackHash":"a01bf420626e980be5b923e60ed4197eb3b2ef7be6078874163475cee8137261","nodeKey":"build_contract_project","submissionHash":"e458e88f6b733f3ce949467b3a0226fb53f5eb6e2742f7a580b57dd4d6f2d4eb","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51324","feedbackHash":"9355bf9721c615fd79f1906f9970b8c29c34b33f9fc91b519b3dc7ec0f13e1c0","nodeKey":"manifest","submissionHash":"054d85e17fd5b0e92e8c3033dcc51b3857b26f1f23c9f40c2dde8c54ea889825","tag1":"verification:checks","tag2":"acceptance-v2","value":1},{"agentId":"51199","feedbackHash":"a6df35e21d4505e125bdc508eafc0797985ab9262104f7c3f7bb155743ac7e9c","nodeKey":"write_foundry_tests","submissionHash":"397265d1855b63f421c1cb1c96efd8b9f8b43a44f069082f7891675fb6c9cc44","tag1":"verification:checks","tag2":"acceptance-v2","value":1}],"site":null,"snapshotHash":"f9955edc17f432e086f5936b95c454008b812863ff6426b04e7bdf14ec4b864f","state":"completed","submissions":[{"artifacts":[],"attempt":1,"bundleHash":"214d0d647a271128b0ed30a61b77cdc65c233bdd9a73e4fedf1fdfb1b50d8329","device":"54f31a82977e83fd","findings":[],"hash":"054d85e17fd5b0e92e8c3033dcc51b3857b26f1f23c9f40c2dde8c54ea889825","nodeId":"44314dd5-308d-47a0-84bc-910927b4bb1a","outcome":"completed","summary":"Created `launch.json` for `ZTOAdapter` with no constructor arguments, matching the accepted implementation.\n\nSchema and ABI checks passed. `forge build` succeeded; all 40 tests passed, including the protected deployment check and both endpoint-code cases.\n\nOnly `launch.json` is included in the submission changes.","treeHash":"c46c984648c5aa9e720bfcfd3895f1ec47e82797","usage":{"cachedInputTokens":177920,"inputTokens":20931,"model":"gpt-6-astra","outputTokens":3001,"runtime":"codex","turns":3,"wallClockMs":87454}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"e57a8e639cccfbab","findings":[{"citation":"resolved","description":"Boundary guide, payable-function check (msg.value > 0: where does it end up?). lzReceive is payable because LayerZero executors forward the native value requested by the sender's lzReceive option (gas, value). OFTCore._lzReceive (src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:270-309) never reads msg.value, the adapter declares no receive() or fallback(), and by requirement it has no rescue function, so every wei that arrives this way is locked forever. The author documents this in README.md ('Inbound execution value should be zero') and docs/SECURITY.md, but nothing enforces it: the value option is chosen per message by the Robinhood sender, and the adapter cannot stop an executor from attaching it. The remaining lever is operational (enforced options and interface guidance); if the author wants an on-chain guard, reverting in _lzReceive when msg.value != 0 would make the packet retryable with zero value through the endpoint instead of silently stranding the ETH, at the cost of one extra check per receive.","line":117,"path":"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OAppReceiver.sol","reproduction":"State: adapter holds 5e18 ZTO, peers[30416] = Robinhood OFT, endpoint has 1 ether. Call: endpoint -> adapter.lzReceive{value: 0.5 ether}(Origin(30416, peer, 1), guid, abi.encodePacked(bytes32(uint160(BOB)), uint64(5_000_000)), executor, \"\"). Expected: 5e18 ZTO released to BOB and the 0.5 ether either refused or forwarded to BOB. Actual: 5e18 ZTO released to BOB, address(adapter).balance == 0.5 ether afterwards; a plain ETH transfer into the adapter reverts (no receive) and the ABI has no function that moves native balance, so the 0.5 ether is unrecoverable. Verified in a scratch Foundry test with a minimal endpoint mock.","severity":"low","snippet":"    ) public payable virtual {","title":"Native value delivered with lzReceive is stranded in the adapter with no path out"},{"citation":"resolved","description":"Math Precision guide, zero-rounding check with minimum inputs. _removeDust floors amountLD to a multiple of decimalConversionRate = 1e12. For any amountLD in [1, 1e12 - 1] the floor is 0; with minAmountLD = 0 the only slippage guard (amountReceivedLD < minAmountLD) is 0 < 0, which is false, so _debit transfers 0 tokens, _buildMsgAndOptions encodes amountSD = 0, and _lzSend forwards the full native fee to the endpoint. The sender pays the LayerZero fee for a message that moves nothing and the remote OFT mints 0. This is upstream OFT behaviour, the author documents it in README.md ('Amounts below one shared unit with a zero minimum can produce a zero-value message'), and the harm is confined to the caller, so it is recorded for completeness rather than as a defect in the agreed design. A minimal guard would be reverting in _debitView when amountSentLD == 0.","line":408,"path":"src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol","reproduction":"State: ALICE holds 100e18 ZTO, approves adapter for 999_999_999_999, peers[30416] set, endpoint native fee 0.001 ether. Call: ALICE -> adapter.send{value: 0.001 ether}(SendParam(30416, bytes32(uint160(BOB)), 999_999_999_999, 0, \"\", \"\", \"\"), MessagingFee(0.001 ether, 0), ALICE). Expected (per caller intent): revert, or lock a non-zero amount. Actual: returns OFTReceipt(0, 0); ALICE still holds 100e18 ZTO; adapter holds 0; ALICE's ETH balance drops by 0.001 ether; endpoint records one send whose message is abi.encodePacked(bytes32(uint160(BOB)), uint64(0)). Verified in a scratch Foundry test.","severity":"info","snippet":"        if (amountReceivedLD < _minAmountLD) {","title":"Sub-unit amountLD with minAmountLD = 0 sends a zero-amount packet and still pays the messaging fee"},{"citation":"resolved","description":"Numerical Gap guide, view/write seam (the view's math omits a check the write applies). quoteOFT returns maxAmountLD = ZTO.totalSupply() and computes the receipt through _debitView only, which floors dust and checks slippage but never calls _toSD. quoteSend and send both call _toSD, which reverts with AmountSDOverflowed when amountLD / 1e12 > type(uint64).max, i.e. amountLD > 18_446_744_073_709_551_615e12. So quoteOFT reports a sendable receipt for amounts the same contract will reject. Against the live token this is unreachable: ZTO.totalSupply() read on Ethereum mainnet is exactly 1e27 (1e15 shared units, about 1/18_000 of the cap), and the adapter never mints, so no holder can assemble an amount that trips the cap. Recorded so integrators relying on quoteOFT limits know the real bound is min(totalSupply, type(uint64).max * 1e12); the README already says quoteOFT does not guarantee a valid uint64 packet amount.","line":123,"path":"src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol","reproduction":"Input: SendParam(30416, bytes32(uint160(BOB)), (2**64) * 1e12, 0, \"\", \"\", \"\"). Call adapter.quoteOFT(p): returns OFTReceipt(amountSentLD = 18_446_744_073_709_551_616e12, amountReceivedLD = same) with no revert. Call adapter.quoteSend(p, false) or send(p, ...): reverts AmountSDOverflowed(18_446_744_073_709_551_616). Expected: both views agree on whether the amount is sendable. Actual: quoteOFT says yes, quoteSend/send say no. Verified in a scratch Foundry test; not reachable with the live 1e27 supply.","severity":"info","snippet":"        uint256 maxAmountLD = IERC20(this.token()).totalSupply(); // Unused in the default implementation.","title":"quoteOFT omits the uint64 shared-decimal cap that quoteSend and send enforce"}],"hash":"36662fe710317f9e5a0d3dc8f8bac741c48644bac56e75dc472f65bb4fc7f850","nodeId":"9c23e1d8-c2e8-44e8-9978-8e6c9a81c17f","outcome":"completed","summary":"The review is complete. The findings file is written and valid, the scratch test directory is removed, and the working tree holds no new files beyond the ignored findings file and build artefacts.\n\n**Outcome.** The math in this adapter holds. The arithmetic surface is the upstream LayerZero OFT v2 code: a floor to multiples of 10^12, a uint64 cap on the shared-decimal amount with an explicit revert, and a widening multiply on receive that cannot overflow. I traced each with concrete values at zero, one unit below the floor, the cap and one above it, and the existing 256-run round-trip fuzz covers the conservation invariant. No critical, high or medium defect was found in the Math Precision, Boundary or Numerical Gap areas, so no proof test was attached.\n\n**Live-chain checks, done against Ethereum mainnet by read-only calls:**\n- ZTO reports 18 decimals, symbol ZTO, and a plain OpenZeppelin v5 ERC-20 dispatcher with no fee, limit or delegatecall logic. Transfers return true and a zero receiver reverts. The compiled constant and the lossless assumption match the real token.\n- Total supply is 10^27 base units, roughly one eighteen-thousandth of the uint64 shared-decimal cap, so the cap is unreachable for this token.\n- The EndpointV2 address holds code and accepts setDelegate from any caller, so the constructor registers the delegate on the real chain. Both constructor branches are already proven by the deployment test file.\n\n**Reported, all reproduced in a scratch Foundry test before it was deleted:**\n1. Low. Native value forwarded with an authenticated lzReceive stays in the adapter forever. There is no receive function and, by requirement, no rescue path. The author documents it, but nothing on chain prevents a Robinhood sender's value option from stranding ETH here.\n2. Info. An amount below one shared unit with a zero minimum sends a zero-amount packet, locks nothing and still pays the messaging fee. Upstream behaviour, documented, caller-only harm.\n3. Info. quoteOFT reports a receipt for amounts that quoteSend and send reject at the uint64 cap. Unreachable with the live supply, recorded for integrators.\n\n**Coverage.** All eleven listed entry points have a row, plus four invariant rows. Two rows point at findings 1 and 2, the rest hold. Nothing was left unreached.","treeHash":null,"usage":{"cachedInputTokens":1365194,"inputTokens":418,"model":"claude-fable-5-1","outputTokens":27954,"runtime":"claude","turns":39,"wallClockMs":428266}},{"artifacts":[],"attempt":1,"bundleHash":"30377091cb7ad02419d7a50c051053d6cb12627e094532e0458ab810e2d1077f","device":"4fcac33561ba733d","findings":[],"hash":"397265d1855b63f421c1cb1c96efd8b9f8b43a44f069082f7891675fb6c9cc44","nodeId":"78d31c8f-7ea2-4109-8d49-2bd84b725cce","outcome":"completed","summary":"Added failure-path, boundary, fuzz, and multi-actor custody invariant tests under `test/`.\n\nValidation passed offline: `forge build` and all **53 tests**, including **32,768 random invariant calls** with no unexpected reverts.\n\nNo reproducible contract defects found. Tests use local token and endpoint mocks.","treeHash":"7dcd8749a6eb220a04cbedff44f1742152493012","usage":{"cachedInputTokens":762368,"inputTokens":73047,"model":"gpt-6-astra","outputTokens":16355,"runtime":"codex","turns":6,"wallClockMs":343840}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"11e4593175677f7e","findings":[{"citation":"resolved","description":"Area: Invariant (conservation: adapter custody == Robinhood OFT supply) and Flow Gap (execution x periphery x first principles). The home-side credit path transfers the unlocked amount straight to the decoded recipient. The live ZTO token at 0xd782bdea4ef02a0bd391eb9089470c8080f0a68e reverts on transfer to address(0) with its custom error InvalidReceiver(address) (selector 0x9cfea583; confirmed on a mainnet fork), and the vendored mock behaves the same (ERC20InvalidReceiver). The upstream mint/burn OFT (src/vendor/@layerzerolabs/oft-evm/contracts/OFT.sol:86) handles this exact case by redirecting address(0) to 0xdead so the packet can always be executed; the adapter's _credit has no such handling. Consequence: a Robinhood user who calls send with to = bytes32(0) burns their tokens on Robinhood, the LayerZero packet is verified and reaches the Ethereum endpoint, and every execution attempt reverts deterministically. The verified payload can only be cleared by the delegate via the endpoint, which marks it executed without calling lzReceive; the corresponding ZTO then sits in the adapter forever because the contract has no rescue function by requirement. The bridge's conservation invariant (custody == remote supply) is therefore broken permanently by the stranded amount. Harm is to the sender who supplied a zero recipient, so severity is low; it is reported because the packet is wedged rather than rejected at source and because the upstream OFT treats the same input differently on the two ends of the mesh. Fix options that preserve the agreed design: (a) mirror OFT.sol in ZTOAdapter by overriding _credit so a zero recipient releases to 0xdead (semantically a burn, keeps custody == supply); or (b) document that the Robinhood OFT front-end must reject to == bytes32(0). Option (a) is a two-line override in src/ZTOAdapter.sol and needs no vendor edit.","line":106,"path":"src/vendor/@layerzerolabs/oft-evm/contracts/OFTAdapter.sol","reproduction":"State: adapter deployed with mocks (as in test/ZTOAdapter.t.sol setUp), peer set for eid 30416, adapter holds 10e18 ZTO from a prior send. Input: endpoint delivers Origin(30416, peer, 1), guid 0x01, message = abi.encodePacked(bytes32(0), uint64(4e6)) to adapter.lzReceive. Expected (per OFT.sol behaviour on the other end of the mesh): the 4e18 is released to a burn address or the message is otherwise executable so custody == remote supply is restored. Actual: lzReceive reverts with ERC20InvalidReceiver(0x0) (live ZTO: InvalidReceiver(0x0)); a second delivery attempt reverts identically; adapter balance stays 10e18 while Robinhood supply has already fallen by 4e18. Verified with a scratch test (removed): testZeroRecipientPacketIsPermanentlyUndeliverable passed showing deterministic revert on retry and unchanged custody.","severity":"low","snippet":"        innerToken.safeTransfer(_to, _amountLD);","title":"Inbound release to a bytes32(0) recipient is permanently undeliverable; the backing ZTO stays locked with no release path"},{"citation":"resolved","description":"Area: Flow Gap (execution x periphery). lzReceive is payable because EndpointV2.lzReceive forwards msg.value from executor lzReceive options (gas, value). The adapter never uses msg.value, and the brief forbids any rescue function, so any value that arrives this way is locked forever. Two ways value can arrive: a Robinhood sender adds an lzReceiveOption with value > 0 to extraOptions (self-harm, they paid for it in the source fee), or the Robinhood OFT owner sets enforced options with a non-zero value for the 30101 destination, in which case every inbound transfer strands a little ETH. README already instructs operators to use zero receive value; this is recorded so the author can decide whether to add a defensive check. A minimal, design-preserving mitigation is to override _lzReceive in ZTOAdapter and revert when msg.value != 0, which converts the stranding into a retryable failure that surfaces the misconfiguration instead of silently accumulating unreachable ETH. No third party loses funds, so this is informational.","line":117,"path":"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OAppReceiver.sol","reproduction":"State: adapter with mocks, peer set for 30416, adapter holds 10e18 ZTO. Input: vm.deal(ENDPOINT, 1 ether); vm.prank(ENDPOINT); adapter.lzReceive{value: 0.5 ether}(Origin(30416, peer, 1), 0x0, abi.encodePacked(bytes32(uint256(uint160(ALICE))), uint64(1e6)), address(0), \"\"). Expected: either the value is refused or it has an owner-reachable exit. Actual: the call succeeds, ALICE receives 1e18 ZTO, address(adapter).balance == 0.5 ether, and no function in the ABI can move it (a plain call to the adapter with empty data fails: no fallback). Verified with a scratch test (removed): testNativeValueOnReceiveIsStranded passed.","severity":"info","snippet":"    ) public payable virtual {","title":"Native value forwarded with lzReceive is stranded in the adapter (no receive/fallback, no withdrawal by design)"},{"citation":"resolved","description":"Area: Economic Security (break dependencies). Not a code defect; an observed live-chain state that the launch and pairing runbook must treat as mandatory. A ZTOAdapter deployed on a mainnet fork (block 26131078, EVM cancun to execute the live PUSH0 bytecode) registered 0xcecc29b037f5064fcdf45a5c318f132ef76aa551 as delegate on EndpointV2 0x1a44076050125825900e736c501f859c50fE728c as required, but quoteSend for dstEid 30416 reverted with the endpoint string 'Please set your OApp's DVNs and/or Executor'. The Ethereum endpoint has no default send config for the Robinhood eid, so no user can lock tokens and nothing is at risk, but the bridge is non-functional until the delegate sets send/receive libraries, DVNs, confirmations and executor for both directions (README step 4). Because the failure is at quote time and reverts the whole send, there is no partial lock; this is recorded so the judge and author have the exact live symptom and do not read a 'Please set your OApp's DVNs' revert as an adapter bug. Also confirmed live: ZTO has 18 decimals and totalSupply 1e27, so quoteOFT.maxAmountLD (1e27) is encodable in uint64 shared decimals (1e15 < 2^64), and ZTO transfer/transferFrom are lossless, return true, and do not decrement an infinite allowance, so the adapter's lossless-custody assumption holds for this token.","line":57,"path":"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OAppSender.sol","reproduction":"Fork of https://ethereum-rpc.publicnode.com at block 26131078, FOUNDRY_EVM_VERSION=cancun. Deploy new ZTOAdapter(); read EndpointV2.delegates(adapter) -> 0xcecc29b037f5064fcdf45a5c318f132ef76aa551 (constructor branch with code works). vm.prank(owner); adapter.setPeer(30416, bytes32(uint160(0xB0B))); adapter.quoteSend(SendParam(30416, to, 5e18+7, 5e18, 0x0003010011010000000000000000000000000000ea60, \"\", \"\"), false). Expected after configuration: a MessagingFee. Actual before configuration: revert with Error('Please set your OApp\\'s DVNs and/or Executor'). The same call will succeed only after the delegate configures the pathway through the endpoint.","severity":"info","snippet":"        return endpoint.quote(","title":"On the live Ethereum endpoint the 30101->30416 pathway has no default DVN/executor config: quoteSend and send revert until the delegate configures the OApp"}],"hash":"3b059e29e6e402c37f6cd4ffd38165bb2365ada2bf3f9d1222370a2855359a79","nodeId":"eeb39767-ecfc-44c7-b999-48cd9ab3280a","outcome":"completed","summary":"The findings file parses correctly with 3 findings and 14 coverage rows. It is excluded from git by the harness's own `.git/info/exclude`, which is why `git status` shows nothing. The working tree is otherwise clean: no scratch files, no modified sources, and the 39 existing tests still pass.\n\n## Review result\n\nThe adapter is upstream LayerZero OFTAdapter plus two deliberate vendor changes, and within my area (Economic Security, Invariant, Flow Gap) I found no fund-loss defect. The findings are one low and two informational, all written to `.imd-findings.json` with reproductions.\n\n**Live-chain facts I verified** (public RPC, mainnet fork at block 26131078):\n- ZTO is a minimal ERC-20 with 18 decimals and a 1e27 supply. Transfers are lossless, return true, infinite allowances are not decremented, and there is no pause, fee, or blacklist selector in its bytecode. The adapter's lossless-custody assumption holds for this token.\n- Eid 30416 is Robinhood mainnet in LayerZero's deployment metadata, and the endpoint at the fixed address reports eid 30101.\n- A fresh `new ZTOAdapter()` on the fork registers the stated owner as delegate on the real endpoint, so the with-code constructor branch works in production.\n\n**Findings**\n1. **Low.** An inbound release to recipient `bytes32(0)` reverts forever on the live token (InvalidReceiver), while the upstream mint/burn OFT redirects that case to 0xdead. The Robinhood burn has already happened, so the backing ZTO is stranded and custody permanently exceeds remote supply. Self-inflicted by the sender, hence low. A two-line `_credit` override in the adapter would mirror upstream OFT behaviour.\n2. **Info.** Native value forwarded with `lzReceive` is stranded because the adapter has no fallback and, by requirement, no rescue. Only misconfigured or self-paid receive options can cause it.\n3. **Info.** On the live endpoint, `quoteSend` to eid 30416 reverts with \"Please set your OApp's DVNs and/or Executor\". The pathway has no defaults, so the bridge is inert until the delegate configures it. Not a code defect, recorded so the symptom is not misread later.\n\n**Coverage.** All 11 listed entry points have a row. `lzReceive` is marked as having findings 1 and 2; the other ten hold. Three invariant rows are included, with the custody-equals-supply invariant tied to finding 1.\n\n**Not reached.** No full fuzz or invariant campaign beyond the project's 256-run round-trip test, and no review of the Robinhood-side OFT, which does not exist in this tree.","treeHash":null,"usage":{"cachedInputTokens":2331540,"inputTokens":610,"model":"claude-fable-5-1","outputTokens":42682,"runtime":"claude","turns":58,"wallClockMs":625304}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"56e50117311155be","findings":[{"citation":"resolved","description":"DEPENDENCIES.json records per-file SHA-256 hashes and VENDORED.md says exactly two vendored files differ from upstream. Byte-for-byte that is false: the whole vendored tree under src/vendor/@layerzerolabs and src/vendor/@openzeppelin was reformatted (forge fmt style: import brace spacing, signature line wrapping, comment placement), so 30 of the 39 hashed files fail the recorded hash and `diff` against the npm tarballs reports differences in every LayerZero contract. I downloaded the four npm tarballs named in DEPENDENCIES.json and compared each file with comments and whitespace stripped: only OFTAdapter.sol (explicit uint8 _localDecimals, no decimals() call) and OAppCore.sol (setDelegate guarded by _endpoint.code.length != 0) carry code changes, exactly as documented, so there is no hidden modification. The defect is that the documented verification procedure cannot be followed: anyone checking provenance from the recorded hashes gets mismatches on files that are claimed unchanged and cannot distinguish a formatting change from a semantic one without re-deriving the comparison. Either record hashes of the files as vendored (and state that the tree is reformatted), or vendor the upstream bytes unchanged (foundry.toml already excludes src/vendor/** from fmt).","line":23,"path":"docs/VENDORED.md","reproduction":"In the repository root run: sha256sum src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol  -> bc2c9c9c794fe4b02e828cc3ed2b0ad8aaab6a0a5bc2f55d35cf0f9de4263b96, while DEPENDENCIES.json line 19 records 5279e6c361b133d057aed94e17f538567cf3d3bc36ca252779b3e013d339e8f1 for a file VENDORED.md says is unchanged. The same mismatch occurs for OFT.sol, OFTMsgCodec.sol, OAppReceiver.sol, OAppSender.sol, OAppOptionsType3.sol, OAppPreCrimeSimulator.sol, PacketV1Codec.sol, Address.sol and 21 more. Expected: every file listed as unchanged hashes to its recorded value. Actual: only 9 of 39 do (IOAppMsgInspector, IMessagingContext, AddressCast and six OpenZeppelin files).","severity":"low","snippet":"Exactly two vendored source files differ from their upstream originals:","title":"Recorded upstream SHA-256 hashes do not match the vendored tree; 'exactly two files differ' is only true after reformatting"},{"citation":"resolved","description":"Documented as a privileged-power trust assumption, not a permission bypass: all guards hold and the brief requires this owner/delegate. The single EOA 0xcECc...A551 (live nonce 16, no code) is both Ownable owner and the LayerZero delegate registered by the constructor. (1) As owner it may call setPeer(30416, X) for any X; the next packet verified from X on eid 30416 passes lzReceive's peer check and _credit transfers any amount of locked ZTO to any recipient. (2) As delegate it may call EndpointV2.setReceiveLibrary / setConfig for the adapter and install a DVN set it controls, after which a forged packet from the real Robinhood peer verifies and releases custody with no change on the adapter at all. (3) As delegate it may call EndpointV2.clear / nilify / burn on a verified-but-unexecuted inbound packet, permanently stranding ZTO already burned on Robinhood. (4) As owner it may set a reverting msgInspector, which halts send() for everyone (a de facto pause despite the 'no pause' requirement; receives are unaffected). (5) renounceOwnership() removes setPeer/setDelegate forever while the endpoint-side delegate stays in force. None of this is reachable by an unprivileged actor; the README's 'Administrative trust' section covers peer and inspector powers but does not state that the delegate alone can replace the verification stack or drop packets. Mitigation is operational (hardware/multisig custody of the key, a two-step owner transfer), not a code change the brief allows.","line":22,"path":"src/ZTOAdapter.sol","reproduction":"State: adapter holds 5e18 ZTO after a user send. Owner-only path: vm.prank(owner); adapter.setPeer(30416, bytes32(uint256(uint160(attacker)))); then a packet with Origin(30416, bytes32(attacker), n) and message abi.encodePacked(bytes32(attacker), uint64(5e6)) delivered by the endpoint moves 5e18 ZTO to attacker. Delegate-only path on mainnet: owner calls EndpointV2(0x1a44...728c).setConfig(adapter, receiveLib, [ulnConfig with requiredDVNs=[ownerDVN]]) and then verifies and executes a packet whose origin.sender is the real Robinhood peer; adapter accepts it unchanged. Both require the configured key; neither is reachable by a third party.","severity":"info","snippet":"    constructor() OFTAdapter(ZTO, LOCAL_DECIMALS, ENDPOINT, INITIAL_OWNER) Ownable(INITIAL_OWNER) {}","title":"Trust assumption: the owner/delegate key can release all custody by changing peer or verification config, and can drop verified inbound packets"},{"citation":"resolved","description":"Upstream asymmetry between the two ends of the mesh, reported for completeness because it strands value without a rescue path. OFT._credit maps address(0) to 0xdead before minting, but OFTAdapter._credit passes the decoded recipient straight to ZTO.transfer. The live ZTO at 0xd782...A68e is an OpenZeppelin-style ERC-20 (solc 0.8.26, 9 standard selectors, no fee or hook logic) whose transfer to address(0) reverts with ERC20InvalidReceiver. A Robinhood user who sends with SendParam.to == bytes32(0) burns their tokens there, and the resulting inbound packet can never execute here: the endpoint keeps it as a verified payload, every retry reverts, and the matching ZTO stays locked in the adapter with no owner function able to release it. Only the sender who chose a zero recipient is harmed, so this is informational; the fix, if wanted, is to mirror OFT's 0xdead redirect in a _credit override or to validate the recipient in a message inspector on the Robinhood side.","line":106,"path":"src/vendor/@layerzerolabs/oft-evm/contracts/OFTAdapter.sol","reproduction":"With a mock ZTO etched at 0xd782...A68e and 5e18 ZTO locked in the adapter: vm.prank(0x1a44...728c); adapter.lzReceive(Origin(30416, peer, 1), bytes32(0), abi.encodePacked(bytes32(0), uint64(5e6)), address(0), \"\"); Expected (to match the remote OFT): tokens leave custody to a burn address or the packet is handled; Actual: revert ERC20InvalidReceiver(0x0000000000000000000000000000000000000000) on every attempt (existing test testMalformedReceiveAndZeroRecipientDoNotReleaseCustody shows the revert); adapter balance stays 5e18 permanently.","severity":"info","snippet":"        innerToken.safeTransfer(_to, _amountLD);","title":"Inbound transfer to recipient bytes32(0) reverts forever on the adapter side while the remote OFT redirects it to 0xdead"}],"hash":"ad7df0ab8e39acd797435f1b762b8f29ecf171f5da3e53dc2f067d5707861b1a","nodeId":"d7ffb913-3c5e-4454-9f15-baa16bcacd97","outcome":"completed","summary":"The review is complete. The findings file is at `.imd-findings.json` and no repository file was changed (git reports a clean tree apart from the untracked findings file).\n\n**Outcome: no custody-affecting defect found in the adapter.** The application is a thin wrapper over upstream LayerZero OFT code, and I traced every entry point through its guards, state changes and failure paths against the Execution Trace, Periphery and First Principles checklists. Three items are recorded, none above low:\n\n- **Low, provenance.** The vendored tree was reformatted, so 30 of the 39 recorded upstream SHA-256 hashes fail and the \"exactly two files differ\" claim is byte-false. I downloaded the four pinned npm tarballs and compared with comments and whitespace stripped: only the two documented constructor edits are real code changes, so nothing is hidden. The documented verification procedure just cannot be followed as written.\n- **Info, trust assumption.** The single owner and delegate key can release all custody via a peer change or by replacing the receive DVN config at the endpoint, and can drop verified inbound packets. No unprivileged path exists. Recorded as required for privileged powers.\n- **Info, upstream asymmetry.** A Robinhood sender who targets recipient zero burns tokens there, and the inbound packet reverts forever here because the live ZTO rejects transfers to the zero address. Only that sender loses.\n\n**What I verified beyond the source.** The public RPC was reachable, so I checked the live chain: ZTO reports 18 decimals and a 1e9 supply, its runtime has only the nine standard ERC-20 selectors and no arithmetic or call opcodes, so the lossless-transfer assumption holds. The mainnet endpoint reports eid 30101 and supports eid 30416, and LayerZero's chain metadata maps 30416 to Robinhood. The owner address is an EOA. All three hardcoded addresses checksum-match the brief. The existing 39 tests pass, including both constructor cases the brief demanded.\n\n**Coverage.** All 11 listed entry points are marked `holds` with a one-line reason, plus four invariant rows covering the no-code constructor path, custody conservation, deployment constants, and vendored provenance, which carries the low finding. No scratch proof test was written because no finding reached high severity.","treeHash":null,"usage":{"cachedInputTokens":1578118,"inputTokens":354,"model":"claude-fable-5-1","outputTokens":41411,"runtime":"claude","turns":41,"wallClockMs":572480}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"60f85cbc35c28a7e","findings":[{"citation":"resolved","description":"The documentation identifies only OFTAdapter.sol and OAppCore.sol as changed, but 28 of 39 checked-in files differ from the original SHA-256 values in DEPENDENCIES.json. Independently downloading the four recorded NPM archives into memory, verifying each archive integrity and original file hash, and comparing Solidity token sequences confirmed that only the two documented files have changes beyond comments or whitespace. The dependency record correctly labels the hashes as original; the defect is the unqualified claim that all other vendored files are unchanged (also repeated as preserved formatting in README.md). This is a documentation/auditability issue, with no evidence of an additional executable-code change or custody vulnerability. Document the reformatting and distinguish original hashes from final vendored hashes; no contract or configuration change is needed.","line":23,"path":"docs/VENDORED.md","reproduction":"Run sha256sum src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol. Actual: bc2c9c9c794fe4b02e828cc3ed2b0ad8aaab6a0a5bc2f55d35cf0f9de4263b96. DEPENDENCIES.json records 5279e6c361b133d057aed94e17f538567cf3d3bc36ca252779b3e013d339e8f1, yet OFTCore.sol is not one of the two documented changed files. Recompute SHA-256 for each sourceHashes entry at src/vendor/<package>/<entry>: 28 of 39 files mismatch in the reviewed tree. Expected under the quoted claim: mismatches only for the two declared patches. The earlier specialist's count of 30 mismatches does not reproduce; the current count is 28.","severity":"low","snippet":"Exactly two vendored source files differ from their upstream originals:","title":"Vendored-source provenance incorrectly claims only two files differ from upstream"}],"hash":"cdff88785580212a663cff3bcf33ecf3485a1676239ec30546260e10f27c0f53","nodeId":"e3c704f5-dc82-44ea-81b3-74274e386464","outcome":"completed","summary":"Wrote [review findings](/root/.identitymd-722/work/19f40c50-7120-4caa-82d5-cd9dbcdbd38b/e3c704f5-dc82-44ea-81b3-74274e386464/.imd-findings.json):\n\n- One low-severity provenance documentation defect.\n- All 11 entry points covered.\n- Existing Foundry suite and eight focused checks passed.\n\nProduction files are unchanged. Live pathway configuration remains unverified.","treeHash":null,"usage":{"cachedInputTokens":1349376,"inputTokens":270195,"model":"gpt-6-astra","outputTokens":13433,"runtime":"codex","turns":6,"wallClockMs":414399}},{"artifacts":[],"attempt":1,"bundleHash":"1663dd92e4cc07bb80084de852762bbb1fcd34148e8a7f045925702a448c2ffb","device":"393ade31b99d5d5b","findings":[],"hash":"e458e88f6b733f3ce949467b3a0226fb53f5eb6e2742f7a580b57dd4d6f2d4eb","nodeId":"dbe03c28-6692-44ef-b121-47e419c07785","outcome":"completed","summary":"Implemented [ZTOAdapter](/home/imd/.identitymd/work/19f40c50-7120-4caa-82d5-cd9dbcdbd38b/dbe03c28-6692-44ef-b121-47e419c07785/src/ZTOAdapter.sol) with lock/release behavior, six shared decimals, owner-only Robinhood peer configuration, and both constructor cases tested.\n\nLayerZero dependencies are vendored under `src/`; nothing was added under `lib/`.\n\nValidation passed: `forge build`, `forge test` (39 tests, including 256 fuzz runs), and `forge fmt --check`.\n\n[Documentation](/home/imd/.identitymd/work/19f40c50-7120-4caa-82d5-cd9dbcdbd38b/dbe03c28-6692-44ef-b121-47e419c07785/README.md) covers assumptions, deployment, and operations. Robinhood peer and messaging configuration remain deployment responsibilities.","treeHash":"475dbacbdb0b61da00cd0db866c6f1dc069db9a5","usage":{"cachedInputTokens":858112,"inputTokens":85600,"model":"gpt-6-astra","outputTokens":27275,"runtime":"codex","turns":6,"wallClockMs":632622}},{"artifacts":[],"attempt":1,"bundleHash":null,"device":"45aa937328087de3","findings":[{"citation":"resolved","description":"Asymmetry between the two receive-side guards. The real path lzReceive() uses _getPeerOrRevert(_origin.srcEid), which reverts NoPeer when peers[eid] == bytes32(0) (OAppReceiver.sol:122, OAppCore.sol:69-73). The pre-crime path lzReceiveAndRevert() instead filters packets with isPeer(srcEid, sender) (OAppPreCrimeSimulator.sol:50), which is a plain equality: for every eid that has no peer (every eid except 30416, and 30416 itself after the owner removes the peer with setPeer(30416, 0)) a packet whose origin.sender is bytes32(0) compares equal to the unset slot and is treated as trusted. The simulation then runs _lzReceive -> _credit and releases custody to the recipient encoded in the attacker-chosen message before the mandatory SimulationResult revert. The same equality is used by allowInitializePath (OAppReceiver.sol:71), which returns true for Origin(eid, bytes32(0), n) whenever the peer slot is empty. No state persists because lzReceiveAndRevert always reverts and the real endpoint never produces a zero sender, so the impact is limited to the pre-crime oracle: an off-chain pre-crime run (or any caller of lzReceiveAndRevert) is told that a packet lzReceive would reject executes successfully and drains custody, which inverts the purpose of the simulation. It also means the 'trusted' set reported by isPeer() is wider than the set lzReceive enforces, so any future code or tooling that keys on isPeer() inherits a hole. Minimal fix that preserves upstream behaviour: in ZTOAdapter override isPeer to `return _eid == ROBINHOOD_EID && _peer != bytes32(0) && peers[_eid] == _peer;` (or at least `_peer != bytes32(0)`), and optionally override allowInitializePath the same way.","line":343,"path":"src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol","reproduction":"State: fresh ZTOAdapter with endpoint and token code present, owner has set peers[30416]=P, adapter holds 5 ZTO. (1) vm.prank(ENDPOINT); adapter.lzReceive(Origin(1, bytes32(0), 1), 0, abi.encodePacked(bytes32(uint160(BOB)), uint64(5e6)), address(0), \"\") -> reverts NoPeer(1) as intended. (2) adapter.isPeer(1, bytes32(0)) -> returns true (expected false). (3) From a contract implementing buildSimulationResult() view, call adapter.lzReceiveAndRevert([InboundPacket(Origin(1, bytes32(0), 1), 30101, adapter, 0, 0, address(0), sameMessage, \"\")]). Inside buildSimulationResult, token.balanceOf(BOB) == 5e18 and token.balanceOf(adapter) == 0, i.e. the untrusted packet was executed and custody released; the call then reverts SimulationResult(\"sim\") and balances roll back. Expected: the packet is skipped by the trust filter exactly as lzReceive rejects it. (4) Variant: owner calls setPeer(30416, bytes32(0)); now isPeer(30416, bytes32(0)) and allowInitializePath(Origin(30416, bytes32(0), 1)) both return true while lzReceive for that origin reverts NoPeer(30416). Verified with test/scratch/Review.t.sol (test_simulationAdmitsZeroSenderOnUnconfiguredEid, test_simulationCreditObservedForZeroSender, test_simulationAdmitsZeroSenderAfterPeerRemoval).","severity":"low","snippet":"    function isPeer(uint32 _eid, bytes32 _peer) public view virtual override returns (bool) {\n        return peers[_eid] == _peer;\n    }","title":"Simulation trust filter (isPeer) accepts a zero sender for any endpoint without a peer, unlike lzReceive"},{"citation":"resolved","description":"Branch asymmetry between the two writers of the endpoint delegate. The constructor path (OAppCore.sol:29) reverts InvalidDelegate when _delegate == address(0), but the owner-only setDelegate that the brief requires as the fallback registration path forwards any value, including zero, to endpoint.setDelegate. The production EndpointV2.setDelegate performs no validation either, so the owner can clear the delegate mapping. With a zero delegate nobody can change send/receive libraries, DVN configuration or skip/clear/nilify packets for this OApp until the owner calls setDelegate again (the adapter itself exposes no other endpoint-config call). This is owner-only and fully recoverable, so it is a consistency note, not a permission bypass; it is reported because the author deliberately changed the constructor branch and left the fallback branch without the same check. Fix: `if (_delegate == address(0)) revert InvalidDelegate();` in setDelegate (or in a ZTOAdapter override).","line":82,"path":"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OAppCore.sol","reproduction":"State: endpoint code present, adapter deployed, endpoint.delegates(adapter) == OWNER (set by constructor). Call vm.prank(OWNER); adapter.setDelegate(address(0)). Actual: call succeeds and endpoint.delegates(adapter) == address(0). Expected (by symmetry with the constructor): revert InvalidDelegate(). Verified with test/scratch/Review.t.sol test_setDelegateAcceptsZero.","severity":"info","snippet":"    function setDelegate(address _delegate) public onlyOwner {\n        endpoint.setDelegate(_delegate);\n    }","title":"setDelegate accepts address(0) although the constructor rejects a zero delegate"},{"citation":"resolved","description":"Documented, intended power; recorded here as the trust boundary the launch relies on, not as a bypass. The onlyOwner guard holds and the eid restriction works, but the value of peers[30416] is the only authentication of inbound release requests. Whoever controls the owner key can repoint the peer to any Robinhood contract they control, after which every message that contract emits (once verified by the configured DVNs) is honoured by lzReceive and _credit transfers the requested amount of locked ZTO to any recipient. The same call rejects all in-flight packets from the legitimate Robinhood OFT with OnlyPeer until the peer is restored, so a peer change while packets are pending strands those returns. Independently, the LayerZero delegate (0xcecc..., set in the constructor on the real chain, changeable via setDelegate) can on the real EndpointV2 change the receive library and DVN set for this OApp, which is an equivalent route to forged inbound messages, and can clear or nilify verified packets so that burned Robinhood tokens are never released here. Owner-controlled setMsgInspector and setEnforcedOptions can also halt all outbound sends (inspector revert / invalid enforced options), which is an outbound pause even though the brief says 'no pause'; inbound releases are unaffected. The live ZTO token (checked over RPC) is a minimal ERC-20 with only the nine standard selectors, 18 decimals and 1e27 supply, so no third-party token admin can freeze custody; the owner and delegate keys are the only privileged actors. README 'Administrative trust' already states this.","line":25,"path":"src/ZTOAdapter.sol","reproduction":"State: adapter holds 5 ZTO locked by ALICE, peers[30416] = legitimate OFT P. Owner (or anyone holding its key) calls adapter.setPeer(30416, bytes32(uint160(ATTACKER_OAPP))). Endpoint then delivers Origin(30416, ATTACKER_OAPP, 1) with message abi.encodePacked(bytes32(uint160(ATTACKER)), uint64(5e6)): adapter.lzReceive succeeds, token.balanceOf(ATTACKER) == 5e18, adapter custody == 0. A pending legitimate packet Origin(30416, P, 2) now reverts OnlyPeer(30416, P). Preconditions: compromise or misuse of the single owner key; no unprivileged amplifier exists. Verified with test/scratch/Review.t.sol test_ownerPeerReplacementReleasesCustody.","severity":"info","snippet":"    function setPeer(uint32 eid, bytes32 peer) public override onlyOwner {\n        if (eid != ROBINHOOD_EID) revert UnsupportedEndpoint(eid);\n        _setPeer(eid, peer);\n    }","title":"Trust assumption: the owner's setPeer and the registered delegate each reach the full ZTO custody"},{"citation":"resolved","description":"The adapter uses OpenZeppelin Ownable (single step) rather than Ownable2Step. transferOwnership to a mistyped or non-controllable address, or renounceOwnership, is irreversible and leaves no account able to call setPeer, setDelegate, setEnforcedOptions or setMsgInspector. Because the only remote is a single Robinhood OFT and there is no upgrade or rescue path by requirement, losing the owner means the peer can never be replaced if the Robinhood side must be redeployed, and the registered delegate keeps endpoint authority with no on-chain counterpart able to rotate it. This matches 'standard OApp semantics' requested by the brief and is documented in the README; it is recorded as the trust assumption the judge should see, not as a defect requiring a design change. If the requester wants protection, Ownable2Step preserves the owner model while making the transfer confirmable; renounce can be overridden to revert.","line":76,"path":"src/vendor/@openzeppelin/contracts/access/Ownable.sol","reproduction":"(a) vm.prank(OWNER); adapter.renounceOwnership(); then adapter.owner() == address(0) and vm.prank(OWNER); adapter.setPeer(30416, bytes32(0)) reverts OwnableUnauthorizedAccount(OWNER); endpoint.delegates(adapter) is still OWNER. (b) vm.prank(OWNER); adapter.transferOwnership(address(0xdead)); adapter.owner() == 0xdead immediately, with no acceptance step, and the former owner can no longer call setPeer. Verified with test/scratch/Review.t.sol test_renounceFreezesPeerConfigButDelegateSurvives and test_transferOwnershipIsSingleStep.","severity":"info","snippet":"    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }","title":"Trust assumption: single-step transferOwnership and renounceOwnership can permanently freeze peer configuration"}],"hash":"f06b1ca75411d2e4b9df9d5e515c9fa8a2a5a67d859613a8e419fbfd87242064","nodeId":"52f5c20b-ad22-4abf-8c97-b8584acfe184","outcome":"completed","summary":"The review is complete and `.imd-findings.json` holds four substantiated findings plus a coverage record for all eleven entry points and four invariants.\n\n**Outcome.** No critical, high or medium defect in the permission model. The owner-only guards hold on every setter, the endpoint-only and peer checks hold on `lzReceive`, the self-only check holds on the simulation entry, and no storage variable has a writer with a weaker guard than its siblings. The constructor behaves as the brief requires in both branches, and the owner is the compiled-in constant rather than the factory.\n\n**Findings reported.**\n- **Low.** The pre-crime trust filter `isPeer` is a plain equality, so a packet with a zero sender is \"trusted\" for every endpoint id that has no peer, and for 30416 after the owner clears the peer. The real receive path rejects the same origin with NoPeer. Nothing persists because the simulation always reverts, but it misreports a rejected packet as a successful custody release, and `allowInitializePath` shares the quirk. Fix is a one-line override in ZTOAdapter.\n- **Info.** The owner-only `setDelegate` accepts a zero address while the constructor rejects one. Owner-only and recoverable, but a branch asymmetry the author introduced next to the code they changed.\n- **Info.** Trust assumption: whoever holds the owner key can repoint the peer and release all custody to any recipient, and the delegate has an equivalent route through endpoint configuration. Inspector and enforced options also give the owner an outbound pause despite \"no pause\" in the brief. Documented in the README.\n- **Info.** Trust assumption: single-step ownership transfer and renounce are irreversible and strand peer configuration while the delegate survives.\n\n**External dependency checked live.** Over a public RPC, the ZTO token has only the nine standard ERC-20 selectors with no owner, pause, blacklist or proxy, reports 18 decimals and a supply of 1e27, well under the uint64 shared-decimals cap. The endpoint reports eid 30101 and no LZ token.\n\n**Verification.** The project's 39 tests pass. Eight scratch tests under `test/scratch/Review.t.sol` reproduce every finding and remain in place as allowed. All snippets and line anchors were checked against the tree.\n\n**Coverage.** Access Control, Asymmetry and Trust Gap guides were applied in full to all eleven entry points. The Trust Gap pass found no unprivileged amplifier for any owner action, so the owner-power items stay at info as trust assumptions rather than defects.","treeHash":null,"usage":{"cachedInputTokens":1760122,"inputTokens":450,"model":"claude-fable-5-1","outputTokens":33827,"runtime":"claude","turns":40,"wallClockMs":466688}}],"verification":[{"checks":[{"durationMs":4349,"exitCode":0,"name":"build","output":"Compiling 73 files with Solc 0.8.26\nSolc 0.8.26 finished in 3.96s\nCompiler run successful!\nwarning[locked-ether]: contract can receive ETH but has no mechanism to send it out\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol:13:19\n   │\n13 │ abstract contract OAppPreCrimeSimulator is IOAppPreCrimeSimulator, Ownable {\n   │                   ━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/locked-ether\n\nwarning[controlled-delegatecall]: `delegatecall` target is not provably trusted\n    ╭▸ src/vendor/@openzeppelin/contracts/utils/Address.sol:105:51\n    │\n105 │         (bool success, bytes memory returndata) = target.delegatecall(data);\n    │                                                   ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/controlled-delegatecall\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol:11:18\n   │\n11 │         result = bytes32(_addressBytes);\n   │                  ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes32' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol:32:26\n   │\n32 │     function setPreCrime(address _preCrime) public virtual onlyOwner {\n   │                          ━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol:39:26\n   │\n39 │         result = address(bytes20(_addressBytes));\n   │                          ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes20' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[calls-loop]: external call inside a loop\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol:59:13\n   │\n59 │ ┏             this.lzReceiveSimulate{value: packet.value}(\n60 │ ┃                 packet.origin, packet.guid, packet.message, packet.executor, packet.extraData\n61 │ ┃             );\n   │ ┗━━━━━━━━━━━━━┛\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:104:30\n    │\n104 │     function setMsgInspector(address _msgInspector) public virtual onlyOwner {\n    │                              ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[locked-ether]: contract can receive ETH but has no mechanism to send it out\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OAppReceiver.sol:12:19\n   │\n12 │ abstract contract OAppReceiver is IOAppReceiver, OAppCore {\n   │                   ━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/locked-ether\n\nwarning[arbitrary-send-erc20]: `transferFrom` uses an arbitrary `from`; require it to equal `msg.sender` or `address(this)`\n   ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTAdapter.sol:81:9\n   │\n81 │         innerToken.safeTransferFrom(_from, address(this), amountSentLD);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/arbitrary-send-erc20\n\nwarning[locked-ether]: contract can receive ETH but has no mechanism to send it out\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol:17:19\n   │\n17 │ abstract contract OApp is OAppSender, OAppReceiver {\n   │                   ━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/locked-ether\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:223:9\n    │\n223 │         emit OFTSent(msgReceipt.guid, _sendParam.dstEid, msg.sender, amountSentLD, amountReceivedLD);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:256:38\n    │\n256 │         if (inspector != address(0)) IOAppMsgInspector(inspector).inspect(message, options);\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:308:9\n    │\n308 │         emit OFTReceived(_guid, _origin.srcEid, toAddress, amountReceivedLD);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:356:16\n    │\n356 │         return (_amountLD / decimalConversionRate) * decimalConversionRate;\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:379:16\n    │\n379 │         return uint64(_amountSD);\n    │                ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol:48:9\n   │\n48 │         emit EnforcedOptionSet(_enforcedOptions);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol:97:43\n   │\n97 │         if (optionsType != OPTION_TYPE_3) revert InvalidOptions(_options);\n   │                                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\n","passed":true},{"durationMs":230,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 7 tests for test/ZTOAdapterDeployment.t.sol:ZTOAdapterDeploymentTest\n[PASS] testConstructorNeverReadsTokenMetadataEvenWhenCodeExists() (gas: 2319064)\n[PASS] testConstructorPropagatesFailureWhenEndpointHasCode() (gas: 1431928)\n[PASS] testConstructorRegistersDelegateWithEndpointCodeAndNoTokenCode() (gas: 1404365)\n[PASS] testConstructorWithNeitherDependencyDeployed() (gas: 72443)\n[PASS] testDeferredDelegateRegistrationIsOwnerOnly() (gas: 1512131)\n[PASS] testExplicitSetDelegateDoesNotSilentlySucceedWithoutCode() (gas: 31064)\n[PASS] testFactoryCreate2DeploymentAndRuntimeConstraints() (gas: 7724522)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 55.67ms (30.03ms CPU time)\n\nRan 32 tests for test/ZTOAdapter.t.sol:ZTOAdapterTest\n[PASS] testComposeReceiveUsesLocalAmountAndRollsBackIfQueueFails() (gas: 939308)\n[PASS] testDelegateChangeAndOwnershipTransferAreSeparate() (gas: 240945)\n[PASS] testDustCannotSatisfyMinimum() (gas: 161622)\n[PASS] testEndpointRefundGoesToRequestedAddress() (gas: 379285)\n[PASS] testEndpointSendFailureRollsBackTokenAndETH() (gas: 257380)\n[PASS] testEnforcedOptionsAndComposeSenderEncoding() (gas: 773956)\n[PASS] testFalseReturningTokenCannotLockOrRelease() (gas: 642642)\n[PASS] testFuzzRoundTripConservesSupplyAndLeavesDust(uint64,uint256) (runs: 256, μ: 1217338, ~: 1220047)\n[PASS] testIncorrectMsgValueAndStaleFeeRevertAtomically() (gas: 379096)\n[PASS] testInspectorRejectionAppliesToQuoteAndSend() (gas: 398252)\n[PASS] testInterfaceVersionsAndPathInitialization() (gas: 101568)\n[PASS] testInvalidOptionsRevertAndAdminHooksRequireOwner() (gas: 337449)\n[PASS] testLzTokenPaymentRequiresAvailabilityAndApproval() (gas: 1797151)\n[PASS] testMalformedReceiveAndZeroRecipientDoNotReleaseCustody() (gas: 438100)\n[PASS] testMaximumSharedDecimalAmountIsSupported() (gas: 587720)\n[PASS] testNoReturnTokenIsSupported() (gas: 572836)\n[PASS] testOnlyOwnerCanSetPeer() (gas: 85198)\n[PASS] testOwnerCannotEnableAnotherChain() (gas: 35425)\n[PASS] testPeerRemovalBlocksSendQuoteAndReceive() (gas: 236445)\n[PASS] testQuoteHasNoApplicationFeeAndDoesNotMoveTokens() (gas: 69540)\n[PASS] testReceiveRejectsNonEndpointWrongPeerAndWrongSource() (gas: 468749)\n[PASS] testReceiveReleasesCustodyAndEmitsReceipt() (gas: 546793)\n[PASS] testRejectedReceiveIsRetryableAndEndpointPreventsReplay() (gas: 647440)\n[PASS] testSendLocksRoundedAmountAndEncodesCanonicalMessage() (gas: 556449)\n[PASS] testSendRequiresApprovalAndRollsBack() (gas: 89758)\n[PASS] testSendRequiresBalanceAndRollsBackAllowance() (gas: 153564)\n[PASS] testSharedDecimalOverflowRevertsAtomically() (gas: 229344)\n[PASS] testSimulationAlwaysRevertsAllCustodyChanges() (gas: 468029)\n[PASS] testSubDustZeroMinimumFollowsUpstreamZeroSendSemantics() (gas: 361407)\n[PASS] testTokenCallbackCannotForgeReceiveOrEnterSimulation() (gas: 1060237)\n[PASS] testTokenRevertOnReceiveRollsBackAndCanRetry() (gas: 667735)\n[PASS] testUnverifiedOrAlteredPacketCannotReleaseCustody() (gas: 487262)\nSuite result: ok. 32 passed; 0 failed; 0 skipped; finished in 55.89ms (67.52ms CPU time)\n\nRan 2 test suites in 58.90ms (111.55ms CPU time): 39 tests passed, 0 failed, 0 skipped (39 total tests)\n","passed":true},{"durationMs":152,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"ZTOAdapter.lzReceive((uint32,bytes32,uint64),bytes32,bytes,address,bytes)\",\"ZTOAdapter.lzReceiveAndRevert(((uint32,bytes32,uint64),uint32,address,bytes32,uint256,address,bytes,bytes)[])\",\"ZTOAdapter.lzReceiveSimulate((uint32,bytes32,uint64),bytes32,bytes,address,bytes)\",\"ZTOAdapter.renounceOwnership()\",\"ZTOAdapter.send((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),(uint256,uint256),address)\",\"ZTOAdapter.setDelegate(address)\",\"ZTOAdapter.setEnforcedOptions((uint32,uint16,bytes)[])\",\"ZTOAdapter.setMsgInspector(address)\",\"ZTOAdapter.setPeer(uint32,bytes32)\",\"ZTOAdapter.setPreCrime(address)\",\"ZTOAdapter.transferOwnership(address)\"],\"files\":{\".gitignore\":3,\"DEPENDENCIES.json\":113,\"README.md\":170,\"docs/SECURITY.md\":69,\"docs/VENDORED.md\":47,\"foundry.toml\":21,\"launch.json\":10,\"src/ZTOAdapter.sol\":29,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/LICENSE-LZBL-1.2\":42,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/LICENSE-MIT\":25,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\":89,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol\":19,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLib.sol\":26,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLibManager.sol\":68,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingChannel.sol\":32,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingComposer.sol\":36,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingContext.sol\":9,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ISendLib.sol\":33,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol\":41,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.sol\":102,\"src/vendor/@layerzerolabs/oapp-evm/LICENSE-MIT\":25,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol\":39,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OAppCore.sol\":85,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OAppReceiver.sol\":138,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OAppSender.sol\":125,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppCore.sol\":52,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppMsgInspector.sol\":22,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppOptionsType3.sol\":42,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppReceiver.sol\":27,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol\":99,\"src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol\":121,\"src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/interfaces/IOAppPreCrimeSimulator.sol\":55,\"src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/interfaces/IPreCrime.sol\":38,\"src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/libs/Packet.sol\":62,\"src/vendor/@layerzerolabs/oft-evm/LICENSE-MIT\":25,\"src/vendor/@layerzerolabs/oft-evm/contracts/OFT.sol\":92,\"src/vendor/@layerzerolabs/oft-evm/contracts/OFTAdapter.sol\":110,\"src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol\":441,\"src/vendor/@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol\":150,\"src/vendor/@layerzerolabs/oft-evm/contracts/libs/OFTComposeMsgCodec.sol\":95,\"src/vendor/@layerzerolabs/oft-evm/contracts/libs/OFTMsgCodec.sol\":83,\"src/vendor/@openzeppelin/contracts/LICENSE\":22,\"src/vendor/@openzeppelin/contracts/access/Ownable.sol\":100,\"src/vendor/@openzeppelin/contracts/interfaces/draft-IERC6093.sol\":161,\"src/vendor/@openzeppelin/contracts/token/ERC20/ERC20.sol\":316,\"src/vendor/@openzeppelin/contracts/token/ERC20/IERC20.sol\":79,\"src/vendor/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":26,\"src/vendor/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":83,\"src/vendor/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":118,\"src/vendor/@openzeppelin/contracts/utils/Address.sol\":159,\"src/vendor/@openzeppelin/contracts/utils/Context.sol\":28,\"src/vendor/@openzeppelin/contracts/utils/introspection/IERC165.sol\":25,\"test/ZTOAdapter.t.sol\":662,\"test/ZTOAdapterDeployment.t.sol\":113,\"test/mocks/EndpointV2Mock.sol\":137,\"test/mocks/MockZTO.sol\":64,\"test/mocks/RobinhoodOFTMock.sol\":10,\"test/vendor/forge-std/Base.sol\":42,\"test/vendor/forge-std/LICENSE-APACHE\":203,\"test/vendor/forge-std/LICENSE-MIT\":25,\"test/vendor/forge-std/Script.sol\":28,\"test/vendor/forge-std/StdAssertions.sol\":685,\"test/vendor/forge-std/StdChains.sol\":286,\"test/vendor/forge-std/StdCheats.sol\":829,\"test/vendor/forge-std/StdConstants.sol\":30,\"test/vendor/forge-std/StdError.sol\":15,\"test/vendor/forge-std/StdInvariant.sol\":122,\"test/vendor/forge-std/StdJson.sol\":277,\"test/vendor/forge-std/StdMath.sol\":43,\"test/vendor/forge-std/StdStorage.sol\":473,\"test/vendor/forge-std/StdStyle.sol\":333,\"test/vendor/forge-std/StdToml.sol\":277,\"test/vendor/forge-std/StdUtils.sol\":209,\"test/vendor/forge-std/Test.sol\":34,\"test/vendor/forge-std/Vm.sol\":2369,\"test/vendor/forge-std/console.sol\":1552,\"test/vendor/forge-std/console2.sol\":4,\"test/vendor/forge-std/interfaces/IERC1155.sol\":105,\"test/vendor/forge-std/interfaces/IERC165.sol\":12,\"test/vendor/forge-std/interfaces/IERC20.sol\":43,\"test/vendor/forge-std/interfaces/IERC4626.sol\":190,\"test/vendor/forge-std/interfaces/IERC6909.sol\":72,\"test/vendor/forge-std/interfaces/IERC721.sol\":164,\"test/vendor/forge-std/interfaces/IERC7540.sol\":144,\"test/vendor/forge-std/interfaces/IERC7575.sol\":241,\"test/vendor/forge-std/interfaces/IMulticall3.sol\":70,\"test/vendor/forge-std/safeconsole.sol\":13937},\"excluded\":[\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"054d85e17fd5b0e92e8c3033dcc51b3857b26f1f23c9f40c2dde8c54ea889825","verifiedTreeHash":"c46c984648c5aa9e720bfcfd3895f1ec47e82797","verifierVersion":"0.1.0+5dba5e5e"},{"checks":[{"durationMs":2913,"exitCode":0,"name":"build","output":"Compiling 74 files with Solc 0.8.26\nSolc 0.8.26 finished in 2.70s\nCompiler run successful!\nwarning[locked-ether]: contract can receive ETH but has no mechanism to send it out\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol:13:19\n   │\n13 │ abstract contract OAppPreCrimeSimulator is IOAppPreCrimeSimulator, Ownable {\n   │                   ━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/locked-ether\n\nwarning[locked-ether]: contract can receive ETH but has no mechanism to send it out\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OAppReceiver.sol:12:19\n   │\n12 │ abstract contract OAppReceiver is IOAppReceiver, OAppCore {\n   │                   ━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/locked-ether\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol:11:18\n   │\n11 │         result = bytes32(_addressBytes);\n   │                  ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes32' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol:32:26\n   │\n32 │     function setPreCrime(address _preCrime) public virtual onlyOwner {\n   │                          ━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol:39:26\n   │\n39 │         result = address(bytes20(_addressBytes));\n   │                          ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes20' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[calls-loop]: external call inside a loop\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol:59:13\n   │\n59 │ ┏             this.lzReceiveSimulate{value: packet.value}(\n60 │ ┃                 packet.origin, packet.guid, packet.message, packet.executor, packet.extraData\n61 │ ┃             );\n   │ ┗━━━━━━━━━━━━━┛\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:104:30\n    │\n104 │     function setMsgInspector(address _msgInspector) public virtual onlyOwner {\n    │                              ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[controlled-delegatecall]: `delegatecall` target is not provably trusted\n    ╭▸ src/vendor/@openzeppelin/contracts/utils/Address.sol:105:51\n    │\n105 │         (bool success, bytes memory returndata) = target.delegatecall(data);\n    │                                                   ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/controlled-delegatecall\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:223:9\n    │\n223 │         emit OFTSent(msgReceipt.guid, _sendParam.dstEid, msg.sender, amountSentLD, amountReceivedLD);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:256:38\n    │\n256 │         if (inspector != address(0)) IOAppMsgInspector(inspector).inspect(message, options);\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:308:9\n    │\n308 │         emit OFTReceived(_guid, _origin.srcEid, toAddress, amountReceivedLD);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:356:16\n    │\n356 │         return (_amountLD / decimalConversionRate) * decimalConversionRate;\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:379:16\n    │\n379 │         return uint64(_amountSD);\n    │                ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[arbitrary-send-erc20]: `transferFrom` uses an arbitrary `from`; require it to equal `msg.sender` or `address(this)`\n   ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTAdapter.sol:81:9\n   │\n81 │         innerToken.safeTransferFrom(_from, address(this), amountSentLD);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/arbitrary-send-erc20\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol:48:9\n   │\n48 │         emit EnforcedOptionSet(_enforcedOptions);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol:97:43\n   │\n97 │         if (optionsType != OPTION_TYPE_3) revert InvalidOptions(_options);\n   │                                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[locked-ether]: contract can receive ETH but has no mechanism to send it out\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol:17:19\n   │\n17 │ abstract contract OApp is OAppSender, OAppReceiver {\n   │                   ━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/locked-ether\n\n","passed":true},{"durationMs":8540,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 7 tests for test/ZTOAdapterDeployment.t.sol:ZTOAdapterDeploymentTest\n[PASS] testConstructorNeverReadsTokenMetadataEvenWhenCodeExists() (gas: 2319064)\n[PASS] testConstructorPropagatesFailureWhenEndpointHasCode() (gas: 1431928)\n[PASS] testConstructorRegistersDelegateWithEndpointCodeAndNoTokenCode() (gas: 1404365)\n[PASS] testConstructorWithNeitherDependencyDeployed() (gas: 72443)\n[PASS] testDeferredDelegateRegistrationIsOwnerOnly() (gas: 1512131)\n[PASS] testExplicitSetDelegateDoesNotSilentlySucceedWithoutCode() (gas: 31064)\n[PASS] testFactoryCreate2DeploymentAndRuntimeConstraints() (gas: 7724522)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 68.27ms (27.17ms CPU time)\n\nRan 44 tests for test/ZTOAdapter.t.sol:ZTOAdapterTest\n[PASS] testComposeReceiveUsesLocalAmountAndRollsBackIfQueueFails() (gas: 939382)\n[PASS] testDelegateChangeAndOwnershipTransferAreSeparate() (gas: 241181)\n[PASS] testDustCannotSatisfyMinimum() (gas: 161678)\n[PASS] testEndpointFailureRollsBackBothZTOAndLzTokenFees() (gas: 1414114)\n[PASS] testEndpointRefundGoesToRequestedAddress() (gas: 379318)\n[PASS] testEndpointSendFailureRollsBackTokenAndETH() (gas: 257476)\n[PASS] testEnforcedOptionsAndComposeSenderEncoding() (gas: 773912)\n[PASS] testFalseReturningTokenCannotLockOrRelease() (gas: 642664)\n[PASS] testFullSupplyCanBeLockedAndReleasedWithoutFee() (gas: 569592)\n[PASS] testFuzzArbitraryNonOwnerCannotChangePeerOrDelegate(address,uint32,bytes32) (runs: 1000, μ: 90484, ~: 90639)\n[PASS] testFuzzNonEndpointAndWrongPeerCannotReleaseFunds(address,bytes32,uint64) (runs: 1000, μ: 440975, ~: 441168)\n[PASS] testFuzzOneWeiAboveRoundedMinimumAlwaysReverts(uint64,uint256) (runs: 1000, μ: 553943, ~: 555074)\nLogs:\n  Bound result 55602408137\n\n[PASS] testFuzzOwnerCannotAddAnyOtherEndpoint(uint32,bytes32) (runs: 1000, μ: 52349, ~: 52430)\n[PASS] testFuzzRoundTripConservesSupplyAndLeavesDust(uint64,uint256) (runs: 256, μ: 1218412, ~: 1220027)\n[PASS] testFuzzTruncatedMessagesCannotReleaseFunds(uint8,bytes32) (runs: 1000, μ: 552288, ~: 551766)\nLogs:\n  Bound result 10\n\n[PASS] testIncorrectMsgValueAndStaleFeeRevertAtomically() (gas: 379158)\n[PASS] testInspectorRejectionAppliesToQuoteAndSend() (gas: 398263)\n[PASS] testInterfaceVersionsAndPathInitialization() (gas: 101591)\n[PASS] testInvalidOptionsRevertAndAdminHooksRequireOwner() (gas: 337482)\n[PASS] testLzTokenPaymentRequiresAvailabilityAndApproval() (gas: 1797306)\n[PASS] testMalformedReceiveAndZeroRecipientDoNotReleaseCustody() (gas: 438211)\n[PASS] testMaximumSharedDecimalAmountIsSupported() (gas: 587765)\n[PASS] testMaximumUint256CannotTruncateSharedAmountAndRollsBack() (gas: 242636)\n[PASS] testNoReturnTokenIsSupported() (gas: 572792)\n[PASS] testOnlyOwnerCanSetPeer() (gas: 85222)\n[PASS] testOwnerCannotEnableAnotherChain() (gas: 35425)\n[PASS] testOwnershipTransferMovesPeerAuthorityButDoesNotMoveCustody() (gas: 719389)\n[PASS] testPeerRemovalBlocksSendQuoteAndReceive() (gas: 236401)\n[PASS] testPeerReplacementRejectsOldInflightPacketAndRestorationAllowsRetry() (gas: 752328)\n[PASS] testQuoteHasNoApplicationFeeAndDoesNotMoveTokens() (gas: 69585)\n[PASS] testReceiveRejectsNonEndpointWrongPeerAndWrongSource() (gas: 468771)\n[PASS] testReceiveReleasesCustodyAndEmitsReceipt() (gas: 546838)\n[PASS] testRejectedReceiveIsRetryableAndEndpointPreventsReplay() (gas: 647485)\n[PASS] testRejectingRefundRollsBackSendAndCanBeRetried() (gas: 872020)\n[PASS] testSendLocksRoundedAmountAndEncodesCanonicalMessage() (gas: 556693)\n[PASS] testSendRequiresApprovalAndRollsBack() (gas: 89705)\n[PASS] testSendRequiresBalanceAndRollsBackAllowance() (gas: 153604)\n[PASS] testSharedDecimalOverflowRevertsAtomically() (gas: 229440)\n[PASS] testSimulationAlwaysRevertsAllCustodyChanges() (gas: 468052)\n[PASS] testSubDustZeroMinimumFollowsUpstreamZeroSendSemantics() (gas: 361363)\n[PASS] testTokenCallbackCannotForgeReceiveOrEnterSimulation() (gas: 1060193)\n[PASS] testTokenRevertOnReceiveRollsBackAndCanRetry() (gas: 667713)\n[PASS] testUnverifiedOrAlteredPacketCannotReleaseCustody() (gas: 487285)\n[PASS] testZeroOneWeiAndSharedUnitBoundaries() (gas: 1248339)\nSuite result: ok. 44 passed; 0 failed; 0 skipped; finished in 68.33ms (415.21ms CPU time)\n\nRan 2 tests for test/ZTOAdapterInvariant.t.sol:ZTOAdapterInvariantTest\n[PASS] invariant_custodySupplyAndActorBalancesAreConserved() (runs: 256, calls: 32768, reverts: 0)\n\n╭------------------+---------------------------+-------+---------+----------╮\n| Contract         | Selector                  | Calls | Reverts | Discards |\n+===========================================================================+\n| ZTOBridgeHandler | burn                      | 3263  | 0       | 0        |\n|------------------+---------------------------+-------+---------+----------|\n| ZTOBridgeHandler | deliverHome               | 3211  | 0       | 0        |\n|------------------+---------------------------+-------+---------+----------|\n| ZTOBridgeHandler | deliverRemote             | 3262  | 0       | 0        |\n|------------------+---------------------------+-------+---------+----------|\n| ZTOBridgeHandler | donate                    | 3282  | 0       | 0        |\n|------------------+---------------------------+-------+---------+----------|\n| ZTOBridgeHandler | lock                      | 3389  | 0       | 0        |\n|------------------+---------------------------+-------+---------+----------|\n| ZTOBridgeHandler | rejectedDeliveryThenRetry | 3305  | 0       | 0        |\n|------------------+---------------------------+-------+---------+----------|\n| ZTOBridgeHandler | rejectedSend              | 3280  | 0       | 0        |\n|------------------+---------------------------+-------+---------+----------|\n| ZTOBridgeHandler | replay                    | 3231  | 0       | 0        |\n|------------------+---------------------------+-------+---------+----------|\n| ZTOBridgeHandler | transferBetweenActors     | 3327  | 0       | 0        |\n|------------------+---------------------------+-------+---------+----------|\n| ZTOBridgeHandler | unauthorizedCalls         | 3218  | 0       | 0        |\n╰------------------+---------------------------+-------+---------+----------╯\n\nLogs:\n  Bound result 100000000000000000001\n  Bound result 30000000000000000000\n  Bound result 20000000000000000000\n  Bound result 50000000000000000007\n  Bound result 1\n  Bound result 4\n  Bound result 17143\n  Bound result 1\n  Bound result 6879\n  Bound result 11155420\n  Bound result 3\n  Bound result 0\n  Bound result 0\n  Bound result 395024849431108255983133\n  Bound result 7\n  Bound result 14\n  Bound result 10\n  Bound result 2\n  Bound result 324\n  Bound result 40\n  Bound result 604168586526285018757512\n  Bound result 10\n  Bound result 42170\n  Bound result 242\n  Bound result 1269\n  Bound result 88476072144549891217\n  Bound result 6253714873\n  Bound result 5590649125452476553\n  Bound result 10658\n  Bound result 35761922445323475933\n  Bound result 2478893115\n  Bound result 36953212461453120330\n  Bound result 15\n  Bound result 34\n  Bound result 179988758648\n  Bound result 11155420\n  Bound result 86068146719\n  Bound result 6465\n  Bound result 4267137671\n  Bound result 100\n  Bound result 22123\n  Bound result 36\n  Bound result 99999999999999999998\n  Bound result 919\n  Bound result 1149\n  Bound result 1000000000000000000\n  Bound result 3\n  Bound result 2\n  Bound result 1000000000001\n  Bound result 810\n  Bound result 51849554012\n  Bound result 4518\n  Bound result 17000\n  Bound result 12672\n  Bound result 50000000000000000007\n  Bound result 5172\n  Bound result 324\n  Bound result 133\n  Bound result 128\n  Bound result 7544\n  Bound result 7733\n  Bound result 850\n  Bound result 44\n  Bound result 10353\n  Bound result 553064317419096193167824\n  Bound result 3999\n  Bound result 401\n  Bound result 874547571054\n  Bound result 125452492762\n  Bound result 604974150568891744018136\n\n[PASS] testHandlerExercisesFailuresAndOutOfOrderSettlement() (gas: 6032762)\nLogs:\n  Bound result 100000000000000000001\n  Bound result 30000000000000000000\n  Bound result 20000000000000000000\n  Bound result 50000000000000000007\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 1000000000000000001\n  Bound result 1000000000000000001\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 1000000000000000000\n  Bound result 123\n  Bound result 50000000000000000000\n  Bound result 1000000000000000001\n  Bound result 1000001000000000000000000\n\nSuite result: ok. 2 passed; 0 failed; 0 skipped; finished in 8.45s (8.45s CPU time)\n\nRan 3 test suites in 8.45s (8.59s CPU time): 53 tests passed, 0 failed, 0 skipped (53 total tests)\n","passed":true},{"durationMs":68,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"ZTOAdapter.lzReceive((uint32,bytes32,uint64),bytes32,bytes,address,bytes)\",\"ZTOAdapter.lzReceiveAndRevert(((uint32,bytes32,uint64),uint32,address,bytes32,uint256,address,bytes,bytes)[])\",\"ZTOAdapter.lzReceiveSimulate((uint32,bytes32,uint64),bytes32,bytes,address,bytes)\",\"ZTOAdapter.renounceOwnership()\",\"ZTOAdapter.send((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),(uint256,uint256),address)\",\"ZTOAdapter.setDelegate(address)\",\"ZTOAdapter.setEnforcedOptions((uint32,uint16,bytes)[])\",\"ZTOAdapter.setMsgInspector(address)\",\"ZTOAdapter.setPeer(uint32,bytes32)\",\"ZTOAdapter.setPreCrime(address)\",\"ZTOAdapter.transferOwnership(address)\"],\"files\":{\".gitignore\":3,\"DEPENDENCIES.json\":113,\"README.md\":170,\"docs/SECURITY.md\":69,\"docs/VENDORED.md\":47,\"foundry.toml\":21,\"src/ZTOAdapter.sol\":29,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/LICENSE-LZBL-1.2\":42,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/LICENSE-MIT\":25,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\":89,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol\":19,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLib.sol\":26,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLibManager.sol\":68,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingChannel.sol\":32,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingComposer.sol\":36,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingContext.sol\":9,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ISendLib.sol\":33,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol\":41,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.sol\":102,\"src/vendor/@layerzerolabs/oapp-evm/LICENSE-MIT\":25,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol\":39,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OAppCore.sol\":85,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OAppReceiver.sol\":138,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OAppSender.sol\":125,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppCore.sol\":52,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppMsgInspector.sol\":22,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppOptionsType3.sol\":42,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppReceiver.sol\":27,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol\":99,\"src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol\":121,\"src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/interfaces/IOAppPreCrimeSimulator.sol\":55,\"src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/interfaces/IPreCrime.sol\":38,\"src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/libs/Packet.sol\":62,\"src/vendor/@layerzerolabs/oft-evm/LICENSE-MIT\":25,\"src/vendor/@layerzerolabs/oft-evm/contracts/OFT.sol\":92,\"src/vendor/@layerzerolabs/oft-evm/contracts/OFTAdapter.sol\":110,\"src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol\":441,\"src/vendor/@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol\":150,\"src/vendor/@layerzerolabs/oft-evm/contracts/libs/OFTComposeMsgCodec.sol\":95,\"src/vendor/@layerzerolabs/oft-evm/contracts/libs/OFTMsgCodec.sol\":83,\"src/vendor/@openzeppelin/contracts/LICENSE\":22,\"src/vendor/@openzeppelin/contracts/access/Ownable.sol\":100,\"src/vendor/@openzeppelin/contracts/interfaces/draft-IERC6093.sol\":161,\"src/vendor/@openzeppelin/contracts/token/ERC20/ERC20.sol\":316,\"src/vendor/@openzeppelin/contracts/token/ERC20/IERC20.sol\":79,\"src/vendor/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":26,\"src/vendor/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":83,\"src/vendor/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":118,\"src/vendor/@openzeppelin/contracts/utils/Address.sol\":159,\"src/vendor/@openzeppelin/contracts/utils/Context.sol\":28,\"src/vendor/@openzeppelin/contracts/utils/introspection/IERC165.sol\":25,\"test/ZTOAdapter.t.sol\":898,\"test/ZTOAdapterDeployment.t.sol\":113,\"test/ZTOAdapterInvariant.t.sol\":487,\"test/mocks/EndpointV2Mock.sol\":137,\"test/mocks/MockZTO.sol\":64,\"test/mocks/RobinhoodOFTMock.sol\":10,\"test/vendor/forge-std/Base.sol\":42,\"test/vendor/forge-std/LICENSE-APACHE\":203,\"test/vendor/forge-std/LICENSE-MIT\":25,\"test/vendor/forge-std/Script.sol\":28,\"test/vendor/forge-std/StdAssertions.sol\":685,\"test/vendor/forge-std/StdChains.sol\":286,\"test/vendor/forge-std/StdCheats.sol\":829,\"test/vendor/forge-std/StdConstants.sol\":30,\"test/vendor/forge-std/StdError.sol\":15,\"test/vendor/forge-std/StdInvariant.sol\":122,\"test/vendor/forge-std/StdJson.sol\":277,\"test/vendor/forge-std/StdMath.sol\":43,\"test/vendor/forge-std/StdStorage.sol\":473,\"test/vendor/forge-std/StdStyle.sol\":333,\"test/vendor/forge-std/StdToml.sol\":277,\"test/vendor/forge-std/StdUtils.sol\":209,\"test/vendor/forge-std/Test.sol\":34,\"test/vendor/forge-std/Vm.sol\":2369,\"test/vendor/forge-std/console.sol\":1552,\"test/vendor/forge-std/console2.sol\":4,\"test/vendor/forge-std/interfaces/IERC1155.sol\":105,\"test/vendor/forge-std/interfaces/IERC165.sol\":12,\"test/vendor/forge-std/interfaces/IERC20.sol\":43,\"test/vendor/forge-std/interfaces/IERC4626.sol\":190,\"test/vendor/forge-std/interfaces/IERC6909.sol\":72,\"test/vendor/forge-std/interfaces/IERC721.sol\":164,\"test/vendor/forge-std/interfaces/IERC7540.sol\":144,\"test/vendor/forge-std/interfaces/IERC7575.sol\":241,\"test/vendor/forge-std/interfaces/IMulticall3.sol\":70,\"test/vendor/forge-std/safeconsole.sol\":13937},\"excluded\":[\"node_modules/\"],\"truncated\":false}","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"397265d1855b63f421c1cb1c96efd8b9f8b43a44f069082f7891675fb6c9cc44","verifiedTreeHash":"7dcd8749a6eb220a04cbedff44f1742152493012","verifierVersion":"0.1.0+5dba5e5e"},{"checks":[{"durationMs":2387,"exitCode":0,"name":"build","output":"Compiling 73 files with Solc 0.8.26\nSolc 0.8.26 finished in 2.20s\nCompiler run successful!\nwarning[locked-ether]: contract can receive ETH but has no mechanism to send it out\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol:13:19\n   │\n13 │ abstract contract OAppPreCrimeSimulator is IOAppPreCrimeSimulator, Ownable {\n   │                   ━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/locked-ether\n\nwarning[locked-ether]: contract can receive ETH but has no mechanism to send it out\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OAppReceiver.sol:12:19\n   │\n12 │ abstract contract OAppReceiver is IOAppReceiver, OAppCore {\n   │                   ━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/locked-ether\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol:32:26\n   │\n32 │     function setPreCrime(address _preCrime) public virtual onlyOwner {\n   │                          ━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[calls-loop]: external call inside a loop\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol:59:13\n   │\n59 │ ┏             this.lzReceiveSimulate{value: packet.value}(\n60 │ ┃                 packet.origin, packet.guid, packet.message, packet.executor, packet.extraData\n61 │ ┃             );\n   │ ┗━━━━━━━━━━━━━┛\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/calls-loop\n\nwarning[missing-zero-check]: address parameter is used in a state write or value transfer without a zero-address check\n    ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:104:30\n    │\n104 │     function setMsgInspector(address _msgInspector) public virtual onlyOwner {\n    │                              ━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/missing-zero-check\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol:11:18\n   │\n11 │         result = bytes32(_addressBytes);\n   │                  ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes32' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[unsafe-typecast]: typecast can truncate values\n   ╭▸ src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol:39:26\n   │\n39 │         result = address(bytes20(_addressBytes));\n   │                          ━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ├ note: consider disabling this lint if you're certain the cast is safe\n   │       \n   │       // casting to 'bytes20' is safe because [explain why]\n   │       // forge-lint: disable-next-line(unsafe-typecast)\n   │       \n   │       \n   ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[controlled-delegatecall]: `delegatecall` target is not provably trusted\n    ╭▸ src/vendor/@openzeppelin/contracts/utils/Address.sol:105:51\n    │\n105 │         (bool success, bytes memory returndata) = target.delegatecall(data);\n    │                                                   ━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/controlled-delegatecall\n\nwarning[arbitrary-send-erc20]: `transferFrom` uses an arbitrary `from`; require it to equal `msg.sender` or `address(this)`\n   ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTAdapter.sol:81:9\n   │\n81 │         innerToken.safeTransferFrom(_from, address(this), amountSentLD);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/arbitrary-send-erc20\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:223:9\n    │\n223 │         emit OFTSent(msgReceipt.guid, _sendParam.dstEid, msg.sender, amountSentLD, amountReceivedLD);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[unused-return]: return value of an external call is not used\n    ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:256:38\n    │\n256 │         if (inspector != address(0)) IOAppMsgInspector(inspector).inspect(message, options);\n    │                                      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/unused-return\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n    ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:308:9\n    │\n308 │         emit OFTReceived(_guid, _origin.srcEid, toAddress, amountReceivedLD);\n    │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[divide-before-multiply]: division before multiplication may lose precision\n    ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:356:16\n    │\n356 │         return (_amountLD / decimalConversionRate) * decimalConversionRate;\n    │                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n    │\n    ╰ help: https://getfoundry.sh/forge/linting/divide-before-multiply\n\nwarning[unsafe-typecast]: typecast can truncate values\n    ╭▸ src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:379:16\n    │\n379 │         return uint64(_amountSD);\n    │                ━━━━━━━━━━━━━━━━━\n    │\n    ├ note: consider disabling this lint if you're certain the cast is safe\n    │       \n    │       // casting to 'uint64' is safe because [explain why]\n    │       // forge-lint: disable-next-line(unsafe-typecast)\n    │       \n    │       \n    ╰ help: https://getfoundry.sh/forge/linting/unsafe-typecast\n\nwarning[reentrancy-events]: event emitted after an external call; reentrancy can reorder or fabricate logs that off-chain consumers rely on\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol:48:9\n   │\n48 │         emit EnforcedOptionSet(_enforcedOptions);\n   │         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/reentrancy-events\n\nwarning[require-revert-in-loop]: `require` or `revert` inside a loop\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol:97:43\n   │\n97 │         if (optionsType != OPTION_TYPE_3) revert InvalidOptions(_options);\n   │                                           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/require-revert-in-loop\n\nwarning[locked-ether]: contract can receive ETH but has no mechanism to send it out\n   ╭▸ src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol:17:19\n   │\n17 │ abstract contract OApp is OAppSender, OAppReceiver {\n   │                   ━━━━\n   │\n   ╰ help: https://getfoundry.sh/forge/linting/locked-ether\n\n","passed":true},{"durationMs":118,"exitCode":0,"name":"test","output":"No files changed, compilation skipped\n\nRan 7 tests for test/ZTOAdapterDeployment.t.sol:ZTOAdapterDeploymentTest\n[PASS] testConstructorNeverReadsTokenMetadataEvenWhenCodeExists() (gas: 2319064)\n[PASS] testConstructorPropagatesFailureWhenEndpointHasCode() (gas: 1431928)\n[PASS] testConstructorRegistersDelegateWithEndpointCodeAndNoTokenCode() (gas: 1404365)\n[PASS] testConstructorWithNeitherDependencyDeployed() (gas: 72443)\n[PASS] testDeferredDelegateRegistrationIsOwnerOnly() (gas: 1512131)\n[PASS] testExplicitSetDelegateDoesNotSilentlySucceedWithoutCode() (gas: 31064)\n[PASS] testFactoryCreate2DeploymentAndRuntimeConstraints() (gas: 7724522)\nSuite result: ok. 7 passed; 0 failed; 0 skipped; finished in 29.16ms (25.38ms CPU time)\n\nRan 32 tests for test/ZTOAdapter.t.sol:ZTOAdapterTest\n[PASS] testComposeReceiveUsesLocalAmountAndRollsBackIfQueueFails() (gas: 939308)\n[PASS] testDelegateChangeAndOwnershipTransferAreSeparate() (gas: 240945)\n[PASS] testDustCannotSatisfyMinimum() (gas: 161622)\n[PASS] testEndpointRefundGoesToRequestedAddress() (gas: 379285)\n[PASS] testEndpointSendFailureRollsBackTokenAndETH() (gas: 257380)\n[PASS] testEnforcedOptionsAndComposeSenderEncoding() (gas: 773956)\n[PASS] testFalseReturningTokenCannotLockOrRelease() (gas: 642642)\n[PASS] testFuzzRoundTripConservesSupplyAndLeavesDust(uint64,uint256) (runs: 256, μ: 1218497, ~: 1220047)\n[PASS] testIncorrectMsgValueAndStaleFeeRevertAtomically() (gas: 379096)\n[PASS] testInspectorRejectionAppliesToQuoteAndSend() (gas: 398252)\n[PASS] testInterfaceVersionsAndPathInitialization() (gas: 101568)\n[PASS] testInvalidOptionsRevertAndAdminHooksRequireOwner() (gas: 337449)\n[PASS] testLzTokenPaymentRequiresAvailabilityAndApproval() (gas: 1797151)\n[PASS] testMalformedReceiveAndZeroRecipientDoNotReleaseCustody() (gas: 438100)\n[PASS] testMaximumSharedDecimalAmountIsSupported() (gas: 587720)\n[PASS] testNoReturnTokenIsSupported() (gas: 572836)\n[PASS] testOnlyOwnerCanSetPeer() (gas: 85198)\n[PASS] testOwnerCannotEnableAnotherChain() (gas: 35425)\n[PASS] testPeerRemovalBlocksSendQuoteAndReceive() (gas: 236445)\n[PASS] testQuoteHasNoApplicationFeeAndDoesNotMoveTokens() (gas: 69540)\n[PASS] testReceiveRejectsNonEndpointWrongPeerAndWrongSource() (gas: 468749)\n[PASS] testReceiveReleasesCustodyAndEmitsReceipt() (gas: 546793)\n[PASS] testRejectedReceiveIsRetryableAndEndpointPreventsReplay() (gas: 647440)\n[PASS] testSendLocksRoundedAmountAndEncodesCanonicalMessage() (gas: 556449)\n[PASS] testSendRequiresApprovalAndRollsBack() (gas: 89758)\n[PASS] testSendRequiresBalanceAndRollsBackAllowance() (gas: 153564)\n[PASS] testSharedDecimalOverflowRevertsAtomically() (gas: 229344)\n[PASS] testSimulationAlwaysRevertsAllCustodyChanges() (gas: 468029)\n[PASS] testSubDustZeroMinimumFollowsUpstreamZeroSendSemantics() (gas: 361407)\n[PASS] testTokenCallbackCannotForgeReceiveOrEnterSimulation() (gas: 1060237)\n[PASS] testTokenRevertOnReceiveRollsBackAndCanRetry() (gas: 667735)\n[PASS] testUnverifiedOrAlteredPacketCannotReleaseCustody() (gas: 487262)\nSuite result: ok. 32 passed; 0 failed; 0 skipped; finished in 29.31ms (44.15ms CPU time)\n\nRan 2 test suites in 29.96ms (58.48ms CPU time): 39 tests passed, 0 failed, 0 skipped (39 total tests)\n","passed":true},{"durationMs":62,"exitCode":0,"name":"source-index","output":"{\"v\":1,\"entryPoints\":[\"ZTOAdapter.lzReceive((uint32,bytes32,uint64),bytes32,bytes,address,bytes)\",\"ZTOAdapter.lzReceiveAndRevert(((uint32,bytes32,uint64),uint32,address,bytes32,uint256,address,bytes,bytes)[])\",\"ZTOAdapter.lzReceiveSimulate((uint32,bytes32,uint64),bytes32,bytes,address,bytes)\",\"ZTOAdapter.renounceOwnership()\",\"ZTOAdapter.send((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),(uint256,uint256),address)\",\"ZTOAdapter.setDelegate(address)\",\"ZTOAdapter.setEnforcedOptions((uint32,uint16,bytes)[])\",\"ZTOAdapter.setMsgInspector(address)\",\"ZTOAdapter.setPeer(uint32,bytes32)\",\"ZTOAdapter.setPreCrime(address)\",\"ZTOAdapter.transferOwnership(address)\"],\"files\":{\".gitignore\":3,\"DEPENDENCIES.json\":113,\"README.md\":170,\"docs/SECURITY.md\":69,\"docs/VENDORED.md\":47,\"foundry.toml\":21,\"src/ZTOAdapter.sol\":29,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/LICENSE-LZBL-1.2\":42,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/LICENSE-MIT\":25,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\":89,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol\":19,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLib.sol\":26,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLibManager.sol\":68,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingChannel.sol\":32,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingComposer.sol\":36,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingContext.sol\":9,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ISendLib.sol\":33,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol\":41,\"src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.sol\":102,\"src/vendor/@layerzerolabs/oapp-evm/LICENSE-MIT\":25,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol\":39,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OAppCore.sol\":85,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OAppReceiver.sol\":138,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/OAppSender.sol\":125,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppCore.sol\":52,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppMsgInspector.sol\":22,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppOptionsType3.sol\":42,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppReceiver.sol\":27,\"src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol\":99,\"src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol\":121,\"src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/interfaces/IOAppPreCrimeSimulator.sol\":55,\"src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/interfaces/IPreCrime.sol\":38,\"src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/libs/Packet.sol\":62,\"src/vendor/@layerzerolabs/oft-evm/LICENSE-MIT\":25,\"src/vendor/@layerzerolabs/oft-evm/contracts/OFT.sol\":92,\"src/vendor/@layerzerolabs/oft-evm/contracts/OFTAdapter.sol\":110,\"src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol\":441,\"src/vendor/@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol\":150,\"src/vendor/@layerzerolabs/oft-evm/contracts/libs/OFTComposeMsgCodec.sol\":95,\"src/vendor/@layerzerolabs/oft-evm/contracts/libs/OFTMsgCodec.sol\":83,\"src/vendor/@openzeppelin/contracts/LICENSE\":22,\"src/vendor/@openzeppelin/contracts/access/Ownable.sol\":100,\"src/vendor/@openzeppelin/contracts/interfaces/draft-IERC6093.sol\":161,\"src/vendor/@openzeppelin/contracts/token/ERC20/ERC20.sol\":316,\"src/vendor/@openzeppelin/contracts/token/ERC20/IERC20.sol\":79,\"src/vendor/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":26,\"src/vendor/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":83,\"src/vendor/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":118,\"src/vendor/@openzeppelin/contracts/utils/Address.sol\":159,\"src/vendor/@openzeppelin/contracts/utils/Context.sol\":28,\"src/vendor/@openzeppelin/contracts/utils/introspection/IERC165.sol\":25,\"test/ZTOAdapter.t.sol\":662,\"test/ZTOAdapterDeployment.t.sol\":113,\"test/mocks/EndpointV2Mock.sol\":137,\"test/mocks/MockZTO.sol\":64,\"test/mocks/RobinhoodOFTMock.sol\":10,\"test/vendor/forge-std/Base.sol\":42,\"test/vendor/forge-std/LICENSE-APACHE\":203,\"test/vendor/forge-std/LICENSE-MIT\":25,\"test/vendor/forge-std/Script.sol\":28,\"test/vendor/forge-std/StdAssertions.sol\":685,\"test/vendor/forge-std/StdChains.sol\":286,\"test/vendor/forge-std/StdCheats.sol\":829,\"test/vendor/forge-std/StdConstants.sol\":30,\"test/vendor/forge-std/StdError.sol\":15,\"test/vendor/forge-std/StdInvariant.sol\":122,\"test/vendor/forge-std/StdJson.sol\":277,\"test/vendor/forge-std/StdMath.sol\":43,\"test/vendor/forge-std/StdStorage.sol\":473,\"test/vendor/forge-std/StdStyle.sol\":333,\"test/vendor/forge-std/StdToml.sol\":277,\"test/vendor/forge-std/StdUtils.sol\":209,\"test/vendor/forge-std/Test.sol\":34,\"test/vendor/forge-std/Vm.sol\":2369,\"test/vendor/forge-std/console.sol\":1552,\"test/vendor/forge-std/console2.sol\":4,\"test/vendor/forge-std/interfaces/IERC1155.sol\":105,\"test/vendor/forge-std/interfaces/IERC165.sol\":12,\"test/vendor/forge-std/interfaces/IERC20.sol\":43,\"test/vendor/forge-std/interfaces/IERC4626.sol\":190,\"test/vendor/forge-std/interfaces/IERC6909.sol\":72,\"test/vendor/forge-std/interfaces/IERC721.sol\":164,\"test/vendor/forge-std/interfaces/IERC7540.sol\":144,\"test/vendor/forge-std/interfaces/IERC7575.sol\":241,\"test/vendor/forge-std/interfaces/IMulticall3.sol\":70,\"test/vendor/forge-std/safeconsole.sol\":13937},\"excluded\":[\"node_modules/\"],\"truncated\":false}","passed":true},{"durationMs":1986,"exitCode":0,"name":"slither","output":"[medium/medium] divide-before-multiply at src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:355: OFTCore._removeDust(uint256) (src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol#355-357) performs a multiplication on the result of a division:\n[medium/medium] unused-return at src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:233: OFTCore._buildMsgAndOptions(SendParam,uint256) (src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol#233-257) ignores return value by IOAppMsgInspector(inspector).inspect(message,options) (src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol#256)\n[low/high] shadowing-local at src/vendor/@layerzerolabs/oft-evm/contracts/OFT.sol:20: OFT.constructor(string,string,address,address)._symbol (src/vendor/@layerzerolabs/oft-evm/contracts/OFT.sol#20) shadows:\n[low/high] shadowing-local at src/vendor/@layerzerolabs/oft-evm/contracts/OFT.sol:20: OFT.constructor(string,string,address,address)._name (src/vendor/@layerzerolabs/oft-evm/contracts/OFT.sol#20) shadows:\n[low/medium] missing-zero-check at src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol:32: OAppPreCrimeSimulator.setPreCrime(address)._preCrime (src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol#32) lacks a zero-check on :\n[low/medium] missing-zero-check at src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:104: OFTCore.setMsgInspector(address)._msgInspector (src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol#104) lacks a zero-check on :\n[low/medium] calls-loop at src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol:45: OAppPreCrimeSimulator.lzReceiveAndRevert(InboundPacket[]) (src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol#45-66) has external calls inside a loop: this.lzReceiveSimulate{value: packet.value}(packet.origin,packet.guid,packet.message,packet.executor,packet.extraData) (src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol#59-61)\n[low/medium] reentrancy-events at src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:204: Reentrancy in OFTCore._send(SendParam,MessagingFee,address) (src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol#204-224):\n[low/medium] reentrancy-events at src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol:270: Reentrancy in OFTCore._lzReceive(Origin,bytes32,bytes,address,bytes) (src/vendor/@layerzerolabs/oft-evm/contracts/OFTCore.sol#270-309):","passed":true},{"durationMs":430,"exitCode":0,"name":"aderyn","output":"[low] centralization-risk at src/ZTOAdapter.sol:25: Centralization Risk (11 places)\n[low] costly-loop at src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol:42: Costly operations inside loop\n[low] internal-function-used-once at src/vendor/@layerzerolabs/oft-evm/contracts/libs/OFTMsgCodec.sol:71: Internal Function Used Only Once (2 places)\n[low] literal-instead-of-constant at src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol:10: Literal Instead of Constant (5 places)\n[low] require-revert-in-loop at src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol:42: Loop Contains `require`/`revert`\n[low] state-no-address-check at src/vendor/@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol:33: Address State Variable Set Without Checks (3 places)\n[low] unsafe-erc20-operation at src/vendor/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol:37: Unsafe ERC20 Operation (4 places)\n[low] unspecific-solidity-pragma at src/vendor/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol:3: Unspecific Solidity Pragma (32 places)\n[low] unused-error at src/vendor/@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppCore.sol:14: Unused Error (24 places)\n[low] unused-import at src/vendor/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol:7: Unused Import","passed":true}],"detail":"all checks passed","evaluation":"checks","profile":"foundry","status":"accepted","submissionHash":"e458e88f6b733f3ce949467b3a0226fb53f5eb6e2742f7a580b57dd4d6f2d4eb","verifiedTreeHash":"475dbacbdb0b61da00cd0db866c6f1dc069db9a5","verifierVersion":"0.1.0+5dba5e5e"}]}