MEDIUM severity: Setting a peer `NttManager` contract for the same chain can cause loss of user funds. **Description:** The current implementation of `NttManager::setPeer` allows the owner to set the NTT Manager as a peer for the same chain ID as the current chain. If the NTT Manager owner accidentally (or otherwise) sets an arbitrary address as a peer `NttManager` address for the same chain, this...

Vulnerable code:
function testTransferToOwnChain() external {
    uint16 localChainId = nttManager.chainId();
    DummyToken token = DummyToken(nttManager.token());
   uint8 decimals = token.decimals();
    nttManager.setPeer(localChainId, toWormholeFormat(address(0x999), decimals);

    address user_A = address(uint160(uint256(keccak256("user_A"))));
    address user_B = address(uint160(uint256(keccak256("user_B"))));

    token.mintDummy(address(user_A), 5 * 10 ** decimals);
    uint256 outboundLimit = 4 * 10 ** decimals;
    nttManager.setOutboundLimit(outboundLimit);

    // chk params before transfer
    IRateLimiter.RateLimitParams memory inboundLimitParams =
        nttManager.getInboundLimitParams(localChainId);
    IRateLimiter.RateLimitParams memory outboundLimitParams =
        nttManager.getOutboundLimitParams();

    assertEq(outboundLimitParams.limit.getAmount(), outboundLimit.trim(decimals, decimals).getAmount());
    assertEq(outboundLimitParams.currentCapacity.getAmount(), outboundLimit.trim(decimals, decimals).getAmount());
    assertEq(inboundLimitParams.limit.getAmount(), 0);
    assertEq(inboundLimitParams.currentCapacity.getAmount(), 0);

    vm.startPrank(user_A);
    uint256 transferAmount = 3 * 10 ** decimals;
    token.approve(address(nttManager), transferAmount);
    nttManager.transfer(transferAmount, localChainId, toWormholeFormat(user_B), false, new bytes(1));

    vm.stopPrank();


    // chk params after transfer

    // assert outbound rate limit has decreased
    outboundLimitParams = nttManager.getOutboundLimitParams();
    assertEq(
        outboundLimitParams.currentCapacity.getAmount(),
        (outboundLimit - transferAmount).trim(decimals, decimals).getAmount()
    );
    assertEq(outboundLimitParams.lastTxTimestamp, initialBlockTimestamp);

    // assert inbound rate limit for destination chain is still 0.
    // the backflow should not override the limit.
    inboundLimitParams =
        nttManager.getInboundLimitParams(localChainId);


    assertEq(inboundLimitParams.limit.getAmount(), 0);
    assertEq(inboundLimitParams.currentCapacity.getAmount(), 0);
}

function testSameChainEndToEndTransfer() public {
    vm.chainId(chainId1);

    // Setting up the transfer
    DummyToken token1 = DummyToken(nttManagerChain1.token());

    uint8 decimals = token1.decimals();
    uint256 sendingAmount = 5 * 10 ** decimals;
    token1.mintDummy(address(userA), 5 * 10 ** decimals);
    vm.startPrank(userA);
    token1.approve(address(nttManagerChain1), sendingAmount);

    vm.recordLogs();

    // Send token through standard means (not relayer)
    {

        uint256 userBalanceBefore = token1.balanceOf(address(userA));
        nttManagerChain1.transfer(sendingAmount, chainId1, bytes32(uint256(uint160(userB))));

        // Balance check on funds going in and out working as expected
        uint256 userBalanceAfter = token1.balanceOf(address(userA));

        require(
            userBalanceBefore - sendingAmount == userBalanceAfter,
            "User should have sent tokens"
        );
    }

    vm.stopPrank();

    // Get and sign the log to go down the other pipe. Thank you to whoever wrote this code in the past!
    Vm.Log[] memory entries = guardian.fetchWormholeMessageFromLog(vm.getRecordedLogs());
    bytes[] memory encodedVMs = new bytes[](entries.length);
    for (uint256 i = 0; i < encodedVMs.length; i++) {
        encodedVMs[i] = guardian.fetchSignedMessageFromLogs(entries[i], chainId1);
    }

    {
        uint256 supplyBefore = token1.totalSupply();

        vm.expectRevert(abi.encodeWithSelector(UnexpectedRecipientNttManagerAddress.selector, toWormholeFormat(address(nttManagerChain1)), toWormholeFormat(address(0x999))));
        wormholeTransceiverChain1.receiveMessage(encodedVMs[0]);
        uint256 supplyAfter = token1.totalSupply();

        // emit log_named_uint("sending amount on chain 1", sendingAmount);
        // emit log_named_uint("minting amount on chain 1", supplyAfter - supplyBefore);
        // // require(supplyAfter > sendingAmount + supplyBefore , "Supplies dont match");
        // // require(token1.balanceOf(userB) == sendingAmount, "User didn't receive tokens");
    }
}