57333 sc high inconsistent handler address decoding prevents any message from being executed
Submitted on Oct 25th 2025 at 10:19:41 UTC by @uhudo for Audit Comp | Folks Finance: Wormhole NTT on Algorand
Report ID: #57333
Report Type: Smart Contract
Report severity: High
Target: https://github.com/Folks-Finance/algorand-ntt-contracts/blob/main/ntt_contracts/transceiver/TransceiverManager.py
Impact: Permanent freezing of funds
Description
Brief / Intro
The problem is that handler_address of a received message is expected to encode message_handler as an application ID at one point and as an application address at another point. This inconsistency prevents any message from being executed.
Consequence: no tokens can be minted on the destination chain while they get permanently locked on the source chain.
Vulnerability Details
TransceiverManagerdefinesmessage_handleras an application ID: https://github.com/Folks-Finance/algorand-ntt-contracts/blob/912c92d5219efe94ae707389da85c93e17e7e36b/ntt_contracts/transceiver/TransceiverManager.py#L62When receiving a message (
attestation_received()), it extractsmessage_handlerfromhandler_addressas if thehandler_addresswere an application ID: https://github.com/Folks-Finance/algorand-ntt-contracts/blob/912c92d5219efe94ae707389da85c93e17e7e36b/ntt_contracts/transceiver/TransceiverManager.py#L194When performing the check for executing a message (
execute_message()inMessageHandlerofNttManager), it treatshandler_addressas an address: https://github.com/Folks-Finance/algorand-ntt-contracts/blob/912c92d5219efe94ae707389da85c93e17e7e36b/ntt_contracts/transceiver/MessageHandler.py#L55Messages are identified via a hash of their contents (
calculate_message_digest()): https://github.com/Folks-Finance/algorand-ntt-contracts/blob/912c92d5219efe94ae707389da85c93e17e7e36b/ntt_contracts/transceiver/TransceiverManager.py#L230
Because the encoding/decoding expectations for handler_address differ (application ID vs address), the same logical message encoded differently yields different message digests. The inconsistency causes the check in execute_message() to fail for all received messages — effectively preventing execution.
Impact Details
No message can be executed due to the mismatch, therefore tokens cannot be minted on the destination chain while they remain permanently locked on the source chain.
References
Defining
message_handleras application ID inTransceiverManager: https://github.com/Folks-Finance/algorand-ntt-contracts/blob/912c92d5219efe94ae707389da85c93e17e7e36b/ntt_contracts/transceiver/TransceiverManager.py#L62Extracting
message_handlerfromhandler_addressas if it were an application ID inattestation_received()ofTransceiverManager: https://github.com/Folks-Finance/algorand-ntt-contracts/blob/912c92d5219efe94ae707389da85c93e17e7e36b/ntt_contracts/transceiver/TransceiverManager.py#L194Performing a check for executing a message as if
handler_addresswas an address inexecute_message()withinMessageHandlerofNttManager: https://github.com/Folks-Finance/algorand-ntt-contracts/blob/912c92d5219efe94ae707389da85c93e17e7e36b/ntt_contracts/transceiver/MessageHandler.py#L55Unique message identifier: https://github.com/Folks-Finance/algorand-ntt-contracts/blob/912c92d5219efe94ae707389da85c93e17e7e36b/ntt_contracts/transceiver/TransceiverManager.py#L230
Proof of Concept
An end-to-end test of all components used in the complete transfer flow demonstrates the bug. Replacing the tests in handle message of NttManager.test.ts with the following shows that executing the delivered message fails with "Message handler address mismatch":
(End of report)
Was this helpful?