TRIAGE (2026-09-08, after the code-review changes): 0 high, 6 medium, all six checked by hand. The four carried over from the first run are unchanged (uninitialized-state on _attestations, the two incorrect-equality hits, unused-return on tryRecover) and remain false positives, as they were triaged in that run. The two new ones, reentrancy-benign and reentrancy-events in VerifierPolicy.queueSetTreasury, both point at the treasury liveness probe added by the review fix: an empty zero-value call to the candidate treasury before the change is queued. The function is onlyOwner, the call carries no value, the only state written afterwards is the owner's own queued change, and a candidate that calls back re-enters as the owner and can do nothing the owner could not do directly. Kept as is: reordering would change source that is already deployed and verified on mainnet, for no security gain. 'forge clean' running (wd: D:\Projects\Monad\packages\contracts) 'forge config --json' running 'forge build --build-info --deny never --skip ./test/** ./script/** --force' running (wd: D:\Projects\Monad\packages\contracts) INFO:Detectors: Detector: incorrect-exp Base64._encode(bytes,bool) (lib/openzeppelin-contracts/contracts/utils/Base64.sol#46-135) has bitwise-xor operator ^ instead of the exponentiation operator **: - mstore(uint256,uint256)(0x3f,ghijklmnopqrstuvwxyz0123456789+/ ^ urlAndFilenameSafe * 0x670) (lib/openzeppelin-contracts/contracts/utils/Base64.sol#81-83) Math.mulDiv(uint256,uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#201-271) has bitwise-xor operator ^ instead of the exponentiation operator **: - inverse = (3 * denominator) ^ 2 (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#256) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-exponentiation INFO:Detectors: Detector: incorrect-shift Base64._decode(bytes) (lib/openzeppelin-contracts/contracts/utils/Base64.sol#136-226) contains an incorrect shift operation: ! 1 << a__decode_asm_0 & 0xffffffd0ffffffc47ff5 (lib/openzeppelin-contracts/contracts/utils/Base64.sol#185-188) Base64._decode(bytes) (lib/openzeppelin-contracts/contracts/utils/Base64.sol#136-226) contains an incorrect shift operation: ! 1 << b__decode_asm_0 & 0xffffffd0ffffffc47ff5 (lib/openzeppelin-contracts/contracts/utils/Base64.sol#190-195) Base64._decode(bytes) (lib/openzeppelin-contracts/contracts/utils/Base64.sol#136-226) contains an incorrect shift operation: ! 1 << c__decode_asm_0 & 0xffffffd0ffffffc47ff5 (lib/openzeppelin-contracts/contracts/utils/Base64.sol#197-202) Base64._decode(bytes) (lib/openzeppelin-contracts/contracts/utils/Base64.sol#136-226) contains an incorrect shift operation: ! 1 << d__decode_asm_0 & 0xffffffd0ffffffc47ff5 (lib/openzeppelin-contracts/contracts/utils/Base64.sol#204-209) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-shift-in-assembly INFO:Detectors: Detector: uninitialized-state MoolamRegistry._attestations (src/MoolamRegistry.sol#67) is never initialized. It is used in: - MoolamRegistry.attest(bytes32,bool,uint16,bytes32) (src/MoolamRegistry.sol#337-356) - MoolamRegistry.attestationCount(bytes32) (src/MoolamRegistry.sol#507-509) - MoolamRegistry.getAttestations(bytes32,uint256,uint256) (src/MoolamRegistry.sol#518-529) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-state-variables INFO:Detectors: Detector: divide-before-multiply Base64._encode(bytes,bool) (lib/openzeppelin-contracts/contracts/utils/Base64.sol#46-135) performs a multiplication on the result of a division: - resultLength = 4 * ((data.length + 2) / 3) (lib/openzeppelin-contracts/contracts/utils/Base64.sol#69-70) Base64._decode(bytes) (lib/openzeppelin-contracts/contracts/utils/Base64.sol#136-226) performs a multiplication on the result of a division: - resultLength = (dataLength / 4) * 3 (lib/openzeppelin-contracts/contracts/utils/Base64.sol#145) Math.mulDiv(uint256,uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#201-271) performs a multiplication on the result of a division: - denominator = denominator / twos (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#239) - inverse = (3 * denominator) ^ 2 (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#256) Math.mulDiv(uint256,uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#201-271) performs a multiplication on the result of a division: - denominator = denominator / twos (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#239) - inverse *= 2 - denominator * inverse (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#259) Math.mulDiv(uint256,uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#201-271) performs a multiplication on the result of a division: - denominator = denominator / twos (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#239) - inverse *= 2 - denominator * inverse (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#261) Math.mulDiv(uint256,uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#201-271) performs a multiplication on the result of a division: - denominator = denominator / twos (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#239) - inverse *= 2 - denominator * inverse (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#261-262) Math.mulDiv(uint256,uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#201-271) performs a multiplication on the result of a division: - denominator = denominator / twos (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#239) - inverse *= 2 - denominator * inverse (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#262) Math.mulDiv(uint256,uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#201-271) performs a multiplication on the result of a division: - denominator = denominator / twos (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#239) - inverse *= 2 - denominator * inverse (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#263-264) Math.mulDiv(uint256,uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#201-271) performs a multiplication on the result of a division: - denominator = denominator / twos (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#239) - inverse *= 2 - denominator * inverse (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#264-265) Math.mulDiv(uint256,uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#201-271) performs a multiplication on the result of a division: - low = low / twos (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#241) - result = low * inverse (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#271) Math.invMod(uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#310-354) performs a multiplication on the result of a division: - quotient = gcd / remainder (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#328-329) - (gcd,remainder) = (remainder,gcd - remainder * quotient) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#329-342) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#divide-before-multiply INFO:Detectors: Detector: incorrect-equality MoolamRegistry.attest(bytes32,bool,uint16,bytes32) (src/MoolamRegistry.sol#337-356) uses a dangerous strict equality: - _passports[passportId].registeredAt == 0 (src/MoolamRegistry.sol#339) MoolamRegistry.rescueNative(address) (src/MoolamRegistry.sol#478-488) uses a dangerous strict equality: - amount == 0 (src/MoolamRegistry.sol#482) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-strict-equalities INFO:Detectors: Detector: unused-return MoolamRegistry._checkGenerator(bool,uint256,bytes32,bytes) (src/MoolamRegistry.sol#636-649) ignores return value by (recovered,err,None) = ECDSA.tryRecover(digest,signature) (src/MoolamRegistry.sol#647) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unused-return INFO:Detectors: Detector: missing-zero-check ReceiverTemplate.setExpectedAuthor(address)._author (src/vendor/chainlink/ReceiverTemplate.sol#110) lacks a zero-check on : - s_expectedAuthor = _author (src/vendor/chainlink/ReceiverTemplate.sol#113) Ownable2Step.transferOwnership(address).newOwner (lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol#41-43) lacks a zero-check on : - _pendingOwner = newOwner (lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol#43) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#missing-zero-address-validation INFO:Detectors: Detector: reentrancy-benign Reentrancy in VerifierPolicy.queueSetTreasury(address) (src/VerifierPolicy.sol#194-201): External calls: - (reachable,None) = who.call{value: 0}() (src/VerifierPolicy.sol#197) State variables written after the call(s): - _queue(OP_SET_TREASURY,abi.encode(who)) (src/VerifierPolicy.sol#200) - _pending[id] = PendingChange({op:op,executeAfter:executeAfter,data:data}) (src/VerifierPolicy.sol#257) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-3 INFO:Detectors: Detector: reentrancy-events Reentrancy in VerifierPolicy.queueSetTreasury(address) (src/VerifierPolicy.sol#194-201): External calls: - (reachable,None) = who.call{value: 0}() (src/VerifierPolicy.sol#197) Event emitted after the call(s): - ChangeQueued(id,op,data,executeAfter) (src/VerifierPolicy.sol#263) - _queue(OP_SET_TREASURY,abi.encode(who)) (src/VerifierPolicy.sol#200) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-4 INFO:Detectors: Detector: timestamp MoolamRegistry.register(PassportInput,WebAuthn.WebAuthnAuth,bytes) (src/MoolamRegistry.sol#259-285) uses timestamp for comparisons Dangerous comparisons: - p.deadline < block.timestamp (src/MoolamRegistry.sol#272) MoolamRegistry.appendEdit(PassportInput,bytes) (src/MoolamRegistry.sol#302-325) uses timestamp for comparisons Dangerous comparisons: - p.deadline < block.timestamp (src/MoolamRegistry.sol#315) MoolamRegistry.attest(bytes32,bool,uint16,bytes32) (src/MoolamRegistry.sol#337-356) uses timestamp for comparisons Dangerous comparisons: - _passports[passportId].registeredAt == 0 (src/MoolamRegistry.sol#339) MoolamRegistry.passportExists(bytes32) (src/MoolamRegistry.sol#496-498) uses timestamp for comparisons Dangerous comparisons: - _passports[id].registeredAt != 0 (src/MoolamRegistry.sol#497) VerifierPolicy.execute(bytes32) (src/VerifierPolicy.sol#215-240) uses timestamp for comparisons Dangerous comparisons: - block.timestamp < change.executeAfter (src/VerifierPolicy.sol#219) VerifierPolicy._queue(bytes32,bytes) (src/VerifierPolicy.sol#251-264) uses timestamp for comparisons Dangerous comparisons: - _pending[id].executeAfter != 0 (src/VerifierPolicy.sol#253) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#block-timestamp INFO:Detectors: Detector: assembly SafeERC20._safeTransfer(IERC20,address,uint256,bool) (lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol#173-195) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol#176-195) SafeERC20._safeTransferFrom(IERC20,address,address,uint256,bool) (lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol#208-237) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol#212-237) SafeERC20._safeApprove(IERC20,address,uint256,bool) (lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol#250-272) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol#253-272) ERC721Utils.checkOnERC721Received(address,address,address,uint256,bytes) (lib/openzeppelin-contracts/contracts/token/ERC721/utils/ERC721Utils.sol#23-46) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/token/ERC721/utils/ERC721Utils.sol#42-44) Base64._encode(bytes,bool) (lib/openzeppelin-contracts/contracts/utils/Base64.sol#46-135) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/Base64.sol#70-135) Base64._decode(bytes) (lib/openzeppelin-contracts/contracts/utils/Base64.sol#136-226) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/Base64.sol#152-226) Bytes.slice(bytes,uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#84-94) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#91-94) Bytes.splice(bytes,uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#115-124) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#119-124) Bytes.replace(bytes,uint256,bytes,uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#149-167) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#163-164) Bytes.concat(bytes[]) (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#180-195) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#189-192) Bytes.toNibbles(bytes) (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#199-239) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#206-239) Bytes._unsafeReadBytesOffset(bytes,uint256) (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#317-326) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#323-326) Panic.panic(uint256) (lib/openzeppelin-contracts/contracts/utils/Panic.sol#49-53) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/Panic.sol#50-53) ShortStrings.toString(ShortString) (lib/openzeppelin-contracts/contracts/utils/ShortStrings.sol#61-69) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/ShortStrings.sol#65-68) StorageSlot.getAddressSlot(bytes32) (lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol#64-67) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol#66-67) StorageSlot.getBooleanSlot(bytes32) (lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol#73-76) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol#75) StorageSlot.getBytes32Slot(bytes32) (lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol#82-84) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol#84) StorageSlot.getUint256Slot(bytes32) (lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol#90-93) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol#93) StorageSlot.getInt256Slot(bytes32) (lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol#97-102) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol#101-102) StorageSlot.getStringSlot(bytes32) (lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol#105-111) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol#109-111) StorageSlot.getStringSlot(string) (lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol#115-120) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol#118-120) StorageSlot.getBytesSlot(bytes32) (lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol#122-129) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol#127-129) StorageSlot.getBytesSlot(bytes) (lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol#131-138) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol#136-138) Strings.toString(uint256) (lib/openzeppelin-contracts/contracts/utils/Strings.sol#40-57) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/Strings.sol#45-48) - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/Strings.sol#50-53) Strings.toChecksumHexString(address) (lib/openzeppelin-contracts/contracts/utils/Strings.sol#105-121) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/Strings.sol#110-112) Strings.escapeJSON(string) (lib/openzeppelin-contracts/contracts/utils/Strings.sol#456-491) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/Strings.sol#459-461) - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/Strings.sol#489-491) Strings._unsafeReadBytesOffset(bytes,uint256) (lib/openzeppelin-contracts/contracts/utils/Strings.sol#498-510) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/Strings.sol#507-510) Strings._unsafeWriteBytesOffset(bytes,uint256,bytes1) (lib/openzeppelin-contracts/contracts/utils/Strings.sol#513-523) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/Strings.sol#516-522) ECDSA.tryRecover(bytes32,bytes) (lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol#59-78) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol#69-73) ECDSA.tryRecoverCalldata(bytes32,bytes) (lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol#83-102) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol#94-97) ECDSA.parse(bytes) (lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol#213-230) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol#215-230) ECDSA.parseCalldata(bytes) (lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol#232-258) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol#237-258) MessageHashUtils.toEthSignedMessageHash(bytes32) (lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol#30-36) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol#32-36) MessageHashUtils.toDataWithIntendedValidatorHash(address,bytes32) (lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol#69-78) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol#73-78) MessageHashUtils.toTypedDataHash(bytes32,bytes32) (lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol#88-97) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol#92-97) MessageHashUtils.toDomainSeparator(bytes1,bytes32,bytes32,uint256,address,bytes32) (lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol#134-172) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol#142-172) MessageHashUtils.toDomainTypeHash(bytes1) (lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol#177-220) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol#181-220) P256._rip7212(bytes32,bytes32,bytes32,bytes32,bytes32) (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#114-130) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#116-130) P256.isValidPublicKey(bytes32,bytes32) (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#181-192) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#185-192) P256._affineFromJacobian(uint256,uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#207-216) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#213-216) P256._jAdd(P256.JPoint,uint256,uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#231-286) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#233-286) P256._jDouble(uint256,uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#290-309) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#296-309) WebAuthn._validateExpectedTypeHash(string,uint256) (lib/openzeppelin-contracts/contracts/utils/cryptography/WebAuthn.sol#128-143) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/cryptography/WebAuthn.sol#132-142) WebAuthn.tryDecodeAuth(bytes) (lib/openzeppelin-contracts/contracts/utils/cryptography/WebAuthn.sol#234-261) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/cryptography/WebAuthn.sol#236) Math.add512(uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#23-28) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#25-28) Math.mul512(uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#35-44) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#40-44) Math.tryMul(uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#71-81) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#73-78) Math.tryDiv(uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#87-93) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#89-93) Math.tryMod(uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#100-106) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#102-106) Math.mulDiv(uint256,uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#201-271) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#223-231) - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#238-246) Math.tryModExp(uint256,uint256,uint256) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#406-424) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#407-424) Math.tryModExp(bytes,bytes,bytes) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#438-464) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#449-464) Math._zeroBytes(bytes) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#465-478) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#469-471) Math.log2(uint256) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#599-647) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#645-647) SafeCast.toUint(bool) (lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#1120-1124) uses assembly - INLINE ASM (lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#1122-1123) ReceiverTemplate._decodeMetadata(bytes) (src/vendor/chainlink/ReceiverTemplate.sol#157-171) uses assembly - INLINE ASM (src/vendor/chainlink/ReceiverTemplate.sol#165-169) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage INFO:Detectors: Detector: pragma 8 different versions of Solidity are used: - Version constraint ^0.8.20 is used by: -^0.8.20 (lib/openzeppelin-contracts/contracts/access/Ownable.sol#2-4) -^0.8.20 (lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol#2-4) -^0.8.20 (lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol#2-4) -^0.8.20 (lib/openzeppelin-contracts/contracts/token/ERC721/utils/ERC721Utils.sol#2-4) -^0.8.20 (lib/openzeppelin-contracts/contracts/utils/Base64.sol#2-4) -^0.8.20 (lib/openzeppelin-contracts/contracts/utils/Context.sol#2-4) -^0.8.20 (lib/openzeppelin-contracts/contracts/utils/Errors.sol#2-4) -^0.8.20 (lib/openzeppelin-contracts/contracts/utils/Panic.sol#2-4) -^0.8.20 (lib/openzeppelin-contracts/contracts/utils/Pausable.sol#2-4) -^0.8.20 (lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol#2-4) -^0.8.20 (lib/openzeppelin-contracts/contracts/utils/ShortStrings.sol#2-4) -^0.8.20 (lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol#3-5) -^0.8.20 (lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol#2-4) -^0.8.20 (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#2-3) -^0.8.20 (lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol#2-4) -^0.8.20 (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#2-4) -^0.8.20 (lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#3-5) -^0.8.20 (lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol#2-4) - Version constraint >=0.6.2 is used by: ->=0.6.2 (lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol#2-4) ->=0.6.2 (lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol#2-4) ->=0.6.2 (lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol#2-4) - Version constraint >=0.4.16 is used by: ->=0.4.16 (lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol#2-4) ->=0.4.16 (lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol#2-4) ->=0.4.16 (lib/openzeppelin-contracts/contracts/interfaces/IERC5267.sol#2-4) ->=0.4.16 (lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol#2-4) ->=0.4.16 (lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol#2-4) - Version constraint >=0.8.4 is used by: ->=0.8.4 (lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol#2-4) - Version constraint ^0.8.24 is used by: -^0.8.24 (lib/openzeppelin-contracts/contracts/token/ERC721/ERC721.sol#2-4) -^0.8.24 (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#2-4) -^0.8.24 (lib/openzeppelin-contracts/contracts/utils/Strings.sol#2-4) -^0.8.24 (lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol#2-4) -^0.8.24 (lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol#2-4) -^0.8.24 (lib/openzeppelin-contracts/contracts/utils/cryptography/WebAuthn.sol#2-4) - Version constraint >=0.5.0 is used by: ->=0.5.0 (lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol#2-4) - Version constraint 0.8.30 is used by: -0.8.30 (src/MoolamReceiver.sol#2) -0.8.30 (src/MoolamRegistry.sol#2) -0.8.30 (src/VerifierPolicy.sol#2) -0.8.30 (src/interfaces/IMoolamRegistry.sol#2) -0.8.30 (src/interfaces/IVerifierPolicy.sol#2) - Version constraint ^0.8.0 is used by: -^0.8.0 (src/vendor/chainlink/IERC165.sol#2) -^0.8.0 (src/vendor/chainlink/IReceiver.sol#2) -^0.8.0 (src/vendor/chainlink/ReceiverTemplate.sol#2) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#different-pragma-directives-are-used INFO:Detectors: Detector: solc-version Version constraint ^0.8.20 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html) - VerbatimInvalidDeduplication - FullInlinerNonExpressionSplitArgumentEvaluationOrder - MissingSideEffectsOnSelectorAccess. It is used by: - ^0.8.20 (lib/openzeppelin-contracts/contracts/access/Ownable.sol#2-4) - ^0.8.20 (lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol#2-4) - ^0.8.20 (lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol#2-4) - ^0.8.20 (lib/openzeppelin-contracts/contracts/token/ERC721/utils/ERC721Utils.sol#2-4) - ^0.8.20 (lib/openzeppelin-contracts/contracts/utils/Base64.sol#2-4) - ^0.8.20 (lib/openzeppelin-contracts/contracts/utils/Context.sol#2-4) - ^0.8.20 (lib/openzeppelin-contracts/contracts/utils/Errors.sol#2-4) - ^0.8.20 (lib/openzeppelin-contracts/contracts/utils/Panic.sol#2-4) - ^0.8.20 (lib/openzeppelin-contracts/contracts/utils/Pausable.sol#2-4) - ^0.8.20 (lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol#2-4) - ^0.8.20 (lib/openzeppelin-contracts/contracts/utils/ShortStrings.sol#2-4) - ^0.8.20 (lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol#3-5) - ^0.8.20 (lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol#2-4) - ^0.8.20 (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#2-3) - ^0.8.20 (lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol#2-4) - ^0.8.20 (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#2-4) - ^0.8.20 (lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#3-5) - ^0.8.20 (lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol#2-4) Version constraint >=0.6.2 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html) - MissingSideEffectsOnSelectorAccess - AbiReencodingHeadOverflowWithStaticArrayCleanup - DirtyBytesArrayToStorage - NestedCalldataArrayAbiReencodingSizeValidation - ABIDecodeTwoDimensionalArrayMemory - KeccakCaching - EmptyByteArrayCopy - DynamicArrayCleanup - MissingEscapingInFormatting - ArraySliceDynamicallyEncodedBaseType - ImplicitConstructorCallvalueCheck - TupleAssignmentMultiStackSlotComponents - MemoryArrayCreationOverflow. It is used by: - >=0.6.2 (lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol#2-4) - >=0.6.2 (lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol#2-4) - >=0.6.2 (lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol#2-4) Version constraint >=0.4.16 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html) - DirtyBytesArrayToStorage - ABIDecodeTwoDimensionalArrayMemory - KeccakCaching - EmptyByteArrayCopy - DynamicArrayCleanup - ImplicitConstructorCallvalueCheck - TupleAssignmentMultiStackSlotComponents - MemoryArrayCreationOverflow - privateCanBeOverridden - SignedArrayStorageCopy - ABIEncoderV2StorageArrayWithMultiSlotElement - DynamicConstructorArgumentsClippedABIV2 - UninitializedFunctionPointerInConstructor_0.4.x - IncorrectEventSignatureInLibraries_0.4.x - ExpExponentCleanup - NestedArrayFunctionCallDecoder - ZeroFunctionSelector. It is used by: - >=0.4.16 (lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol#2-4) - >=0.4.16 (lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol#2-4) - >=0.4.16 (lib/openzeppelin-contracts/contracts/interfaces/IERC5267.sol#2-4) - >=0.4.16 (lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol#2-4) - >=0.4.16 (lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol#2-4) Version constraint >=0.8.4 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html) - FullInlinerNonExpressionSplitArgumentEvaluationOrder - MissingSideEffectsOnSelectorAccess - AbiReencodingHeadOverflowWithStaticArrayCleanup - DirtyBytesArrayToStorage - DataLocationChangeInInternalOverride - NestedCalldataArrayAbiReencodingSizeValidation - SignedImmutables. It is used by: - >=0.8.4 (lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol#2-4) Version constraint >=0.5.0 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html) - DirtyBytesArrayToStorage - ABIDecodeTwoDimensionalArrayMemory - KeccakCaching - EmptyByteArrayCopy - DynamicArrayCleanup - ImplicitConstructorCallvalueCheck - TupleAssignmentMultiStackSlotComponents - MemoryArrayCreationOverflow - privateCanBeOverridden - SignedArrayStorageCopy - ABIEncoderV2StorageArrayWithMultiSlotElement - DynamicConstructorArgumentsClippedABIV2 - UninitializedFunctionPointerInConstructor - IncorrectEventSignatureInLibraries - ABIEncoderV2PackedStorage. It is used by: - >=0.5.0 (lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol#2-4) Version constraint ^0.8.0 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html) - FullInlinerNonExpressionSplitArgumentEvaluationOrder - MissingSideEffectsOnSelectorAccess - AbiReencodingHeadOverflowWithStaticArrayCleanup - DirtyBytesArrayToStorage - DataLocationChangeInInternalOverride - NestedCalldataArrayAbiReencodingSizeValidation - SignedImmutables - ABIDecodeTwoDimensionalArrayMemory - KeccakCaching. It is used by: - ^0.8.0 (src/vendor/chainlink/IERC165.sol#2) - ^0.8.0 (src/vendor/chainlink/IReceiver.sol#2) - ^0.8.0 (src/vendor/chainlink/ReceiverTemplate.sol#2) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity INFO:Detectors: Detector: low-level-calls Low level call in MoolamRegistry.rescueNative(address) (src/MoolamRegistry.sol#478-488): - (ok,None) = to.call{value: amount}() (src/MoolamRegistry.sol#486) Low level call in MoolamRegistry._payOut(address,uint256) (src/MoolamRegistry.sol#590-597): - (ok,None) = to.call{value: amount}() (src/MoolamRegistry.sol#595) Low level call in VerifierPolicy.queueSetTreasury(address) (src/VerifierPolicy.sol#194-201): - (reachable,None) = who.call{value: 0}() (src/VerifierPolicy.sol#197) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls INFO:Detectors: Detector: naming-convention Function EIP712._EIP712Name() (lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol#143-145) is not in mixedCase Function EIP712._EIP712Version() (lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol#154-156) is not in mixedCase Variable MoolamReceiver.REGISTRY (src/MoolamReceiver.sol#22) is not in mixedCase Variable MoolamRegistry._POLICY (src/MoolamRegistry.sol#58) is not in mixedCase Variable MoolamRegistry._AGENT_IDENTITY (src/MoolamRegistry.sol#59) is not in mixedCase Parameter ReceiverTemplate.setForwarderAddress(address)._forwarder (src/vendor/chainlink/ReceiverTemplate.sol#99) is not in mixedCase Parameter ReceiverTemplate.setExpectedAuthor(address)._author (src/vendor/chainlink/ReceiverTemplate.sol#110) is not in mixedCase Parameter ReceiverTemplate.setExpectedWorkflowName(string)._name (src/vendor/chainlink/ReceiverTemplate.sol#118) is not in mixedCase Parameter ReceiverTemplate.setExpectedWorkflowId(bytes32)._id (src/vendor/chainlink/ReceiverTemplate.sol#139) is not in mixedCase Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions INFO:Detectors: Detector: too-many-digits Bytes.toNibbles(bytes) (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#199-239) uses literals with too many digits: - chunk_toNibbles_asm_0 = 0x0000000000000000ffffffffffffffff0000000000000000ffffffffffffffff & chunk_toNibbles_asm_0 << 64 | chunk_toNibbles_asm_0 (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#215-221) Bytes.toNibbles(bytes) (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#199-239) uses literals with too many digits: - chunk_toNibbles_asm_0 = 0x00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff & chunk_toNibbles_asm_0 << 32 | chunk_toNibbles_asm_0 (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#221-224) Bytes.reverseBytes32(bytes32) (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#251-269) uses literals with too many digits: - value = ((value >> 32) & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) | ((value & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) << 32) (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#261-264) Bytes.reverseBytes32(bytes32) (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#251-269) uses literals with too many digits: - value = ((value >> 64) & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) | ((value & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) << 64) (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#264-267) Bytes.reverseBytes16(bytes16) (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#269-281) uses literals with too many digits: - value = ((value & 0xFFFFFFFF00000000FFFFFFFF00000000) >> 32) | ((value & 0x00000000FFFFFFFF00000000FFFFFFFF) << 32) (lib/openzeppelin-contracts/contracts/utils/Bytes.sol#277-280) ShortStrings.slitherConstructorConstantVariables() (lib/openzeppelin-contracts/contracts/utils/ShortStrings.sol#35-116) uses literals with too many digits: - FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF (lib/openzeppelin-contracts/contracts/utils/ShortStrings.sol#41-42) P256._tryVerifyNative(bytes32,bytes32,bytes32,bytes32,bytes32) (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#82-107) uses literals with too many digits: - _rip7212(0xbb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023,0x0000000000000000000000000000000000000000000000000000000000000005,0x0000000000000000000000000000000000000000000000000000000000000001,0xa71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac957,0x5d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b) (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#98-103) P256.slitherConstructorConstantVariables() (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#19-399) uses literals with too many digits: - P = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#32-33) P256.slitherConstructorConstantVariables() (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#19-399) uses literals with too many digits: - N = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551 (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#33-35) P256.slitherConstructorConstantVariables() (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#19-399) uses literals with too many digits: - A = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#36-37) P256.slitherConstructorConstantVariables() (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#19-399) uses literals with too many digits: - P1DIV4 = 0x3fffffffc0000000400000000000000000000000400000000000000000000000 (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#41-42) P256.slitherConstructorConstantVariables() (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#19-399) uses literals with too many digits: - HALF_N = 0x7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8 (lib/openzeppelin-contracts/contracts/utils/cryptography/P256.sol#44-45) Math.log2(uint256) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#599-647) uses literals with too many digits: - r = r | byte(uint256,uint256)(x >> r,0x0000010102020202030303030303030300000000000000000000000000000000) (lib/openzeppelin-contracts/contracts/utils/math/Math.sol#646-647) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#too-many-digits INFO:Detectors: Detector: unindexed-event-address Event Pausable.Paused(address) (lib/openzeppelin-contracts/contracts/utils/Pausable.sol#21-23) has address parameters but no indexed parameters Event Pausable.Unpaused(address) (lib/openzeppelin-contracts/contracts/utils/Pausable.sol#26-28) has address parameters but no indexed parameters Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unindexed-event-address-parameters INFO:Detectors: Detector: constable-states EIP712._nameFallback (lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol#51) should be constant EIP712._versionFallback (lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol#53) should be constant Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-constant INFO:Slither:. analyzed (41 contracts with 102 detectors), 123 result(s) found ================================================================================ MoolamConsent, 2026-09-18 (updated in place after the batch landed) Command: slither . --filter-paths "lib/|test/|script/" Result for the new file: 0 high, 0 medium that stand. Four findings name MoolamConsent or IMoolamConsent and all four are checked by hand below. The rest of the run is the same set already triaged at the top of this file. 1. uninitialized-state on MoolamConsent._history. Same false positive as MoolamRegistry._attestations above: a mapping of dynamic arrays has no initial value to give it, every passport starts empty by definition, and every read handles the empty case explicitly (consentOf and consentAt answer "not stated", historyLength answers zero, historyPage answers an empty page). MoolamConsent._history (src/MoolamConsent.sol#68) is never initialized. It is used in: - MoolamConsent.consentOf(bytes32) (src/MoolamConsent.sol#125-132) - MoolamConsent.consentAt(bytes32,uint64) (src/MoolamConsent.sol#138-153) - MoolamConsent.historyLength(bytes32) (src/MoolamConsent.sol#156-158) - MoolamConsent.historyPage(bytes32,uint256,uint256) (src/MoolamConsent.sol#163-176) - MoolamConsent._record(bytes32,IMoolamConsent.Consent,string) (src/MoolamConsent.sol#181-218) 2. calls-loop on _holderOf, reached from setConsentBatch. New with the batch and deliberate. The call is ownerOf, a view on the registry address fixed at deployment, and it runs once per passport because that is the rule: authority for each passport is read fresh from the registry in the same call, never assumed from the passport before it. The usual danger of this pattern, one failing call stranding the rest, is the wanted behaviour here: a batch is all or nothing. The loop is bounded by MAX_BATCH, and the worst case measures 8,144,656 gas against Monad's 30,000,000 per transaction limit (proofs/gas.txt). MoolamConsent._holderOf(bytes32) (src/MoolamConsent.sol#222-232) has external calls inside a loop: owner_ = IERC721(REGISTRY).ownerOf(uint256(passportId)) (src/MoolamConsent.sol#227-231) Calls stack containing the loop: MoolamConsent.setConsentBatch(bytes32[],IMoolamConsent.Consent,string) MoolamConsent._record(bytes32,IMoolamConsent.Consent,string) 3. timestamp: _record uses block.timestamp for comparisons. On purpose, and named as a non-goal in the design: the clock is the block timestamp, so a time query is only as fine as the chain's clock. What the comparison guards is a rate limit and the strictly increasing order of one passport's entries. A validator who could shift the clock by a few seconds gains nothing: they still cannot write for a passport they do not hold, and they cannot change an entry already written. MoolamConsent._record(...) uses timestamp for comparisons Dangerous comparisons: - block.timestamp < nextAllowedAt (src/MoolamConsent.sol#200) 4. naming-convention: STANDARD, REGISTRY, MIN_INTERVAL, MAX_INFO_BYTES, MAX_PAGE and MAX_BATCH are not mixedCase. They are an immutable and five constants, which are upper case by Solidity convention, and the interface has to declare them as functions with the same names so the generated getters match. MoolamReceiver.REGISTRY carries the identical finding and the identical reason. Variable MoolamConsent.REGISTRY (src/MoolamConsent.sol#40) is not in mixedCase Function IMoolamConsent.STANDARD() (src/interfaces/IMoolamConsent.sol#71) is not in mixedCase Function IMoolamConsent.REGISTRY() (src/interfaces/IMoolamConsent.sol#75) is not in mixedCase Function IMoolamConsent.MIN_INTERVAL() (src/interfaces/IMoolamConsent.sol#79) is not in mixedCase Function IMoolamConsent.MAX_INFO_BYTES() (src/interfaces/IMoolamConsent.sol#83) is not in mixedCase Function IMoolamConsent.MAX_PAGE() (src/interfaces/IMoolamConsent.sol#87) is not in mixedCase Function IMoolamConsent.MAX_BATCH() (src/interfaces/IMoolamConsent.sol#91) is not in mixedCase Nothing else in the run mentions MoolamConsent. Reentrancy, arbitrary-send, unchecked-transfer and the access control detectors have nothing to say about it, which is what a contract with one view call, no money and no owner should look like.