user5565: In the firstGame function, we use the "logging" component of the contract to tell the thread token. It's not obvious to me where this is needed: is there an internal check in the runStep function that this token matches the one in the parameter, i.e. SecondParams? I commented out the line where tt is told and that results in an endless loop, while I expected a failure.

user6113: Because firstGame is the contract that initialises the game, it needs to communicate somehow the generated threadToken to the external world (secondGame in this case). For this kind of communication Contract monad uses tell mechanism.
How does the info flow? You can see it in myTrace function in Week07.TestStateMachine.

(1) callEndpoint @"first" h1 fp - Initialise the game, and firstGame contract internally tells the generated threadToken to anyone interested in it.

(2) tt <- getTT h1 - This function uses observableState function, which "get the observable state w of a contract instance". In our case w in firstGame Contract is (Last ThreadToken).


   firstGame :: forall s. FirstParams -> Contract (Last ThreadToken) s Text ()


(3) let sp = SecondParams {...  spToken = tt ...} - Build params for secondGame using threadToken generated by firstGame contract, tt.

(4) callEndpoint @"second" h2 sp - secondGame plays.


Notice that communication is not direct Contract to Contract but through observableState function
myTrace :: GameChoice -> GameChoice -> EmulatorTrace ()
myTrace c1 c2 = do
    Extras.logInfo $ "first move: " ++ show c1 ++ ", second move: " ++ show c2

    let w1 = knownWallet 1
    let w2 = knownWallet 2

    h1 <- activateContractWallet w1 endpoints
    h2 <- activateContractWallet w2 endpoints

    let pkh1      = mockWalletPaymentPubKeyHash w1
        pkh2      = mockWalletPaymentPubKeyHash w2
        stake     = 5_000_000
        deadline1 = slotToEndPOSIXTime def 5
        deadline2 = slotToEndPOSIXTime def 10

        fp = FirstParams
                { fpSecond         = pkh2
                , fpStake          = stake
                , fpPlayDeadline   = deadline1
                , fpRevealDeadline = deadline2
                , fpNonce          = "SECRETNONCE"
                , fpChoice         = c1
                }

    callEndpoint @"first" h1 fp   -- (1)

    tt <- getTT                   -- (2)

    let sp = SecondParams         -- (3)
                { spFirst          = pkh1
                , spStake          = stake
                , spPlayDeadline   = deadline1
                , spRevealDeadline = deadline2
                , spChoice         = c2
                , spToken          = tt
                }

    void $ Emulator.waitNSlots 3  -- (4)

    callEndpoint @"second" h2 sp

    void $ Emulator.waitNSlots 10
  where
    getTT :: ContractHandle (Last ThreadToken) GameSchema Text -> EmulatorTrace ThreadToken
    getTT h = do
        void $ Emulator.waitNSlots 1
        Last m <- observableState      -- (2)
        case m of
            Nothing -> getTT h
            Just tt -> Extras.logInfo ("read thread token " ++ show tt) >> return tt


5565: <p>In the <code>firstGame</code> function, we use the &quot;logging&quot; component of the contract to <code>tell</code> the thread token. It's not obvious to me where this is needed: is there an internal check in the <code>runStep</code> function that this token matches the one in the parameter, i.e. <code>SecondParams</code>? I commented out the line where <code>tt</code> is <code>told</code> and that results in an endless loop, while I expected a failure.</p>
 6113: <p>Because <strong>firstGame</strong> is the contract that initialises the game, it needs to communicate somehow the generated <strong>threadToken</strong> to the external world (<strong>secondGame</strong> in this case). For this kind of communication <strong>Contract</strong> monad uses <strong>tell</strong> mechanism.</p>
<p>How does the info flow? You can see it in <strong>myTrace</strong> function in <code>Week07.TestStateMachine</code>.</p>
<ul>
<li><p>(1) <code>callEndpoint @&quot;first&quot; h1 fp</code> - Initialise the game, and <strong>firstGame</strong> contract internally tells the generated <strong>threadToken</strong> to anyone interested in it.</p>
</li>
<li><p>(2) <code>tt &lt;- getTT h1</code> - This function uses <strong>observableState</strong> function, which &quot;get the observable state w of a contract instance&quot;. In our case <strong>w</strong> in <strong>firstGame</strong> Contract is <strong>(Last ThreadToken)</strong>.</p>
</li>
</ul>
<pre><code>   firstGame :: forall s. FirstParams -&gt; Contract (Last ThreadToken) s Text ()
</code></pre>
<ul>
<li><p>(3) <code>let sp = SecondParams {...  spToken = tt ...}</code> - Build params for <strong>secondGame</strong> using <strong>threadToken</strong> generated by <strong>firstGame</strong> contract, <strong>tt</strong>.</p>
</li>
<li><p>(4) <code>callEndpoint @&quot;second&quot; h2 sp</code> - <strong>secondGame</strong> plays.</p>
</li>
</ul>
<p><strong>Notice that communication is not direct Contract to Contract but through observableState function</strong></p>
<pre><code>myTrace :: GameChoice -&gt; GameChoice -&gt; EmulatorTrace ()
myTrace c1 c2 = do
    Extras.logInfo $ &quot;first move: &quot; ++ show c1 ++ &quot;, second move: &quot; ++ show c2

    let w1 = knownWallet 1
    let w2 = knownWallet 2

    h1 &lt;- activateContractWallet w1 endpoints
    h2 &lt;- activateContractWallet w2 endpoints

    let pkh1      = mockWalletPaymentPubKeyHash w1
        pkh2      = mockWalletPaymentPubKeyHash w2
        stake     = 5_000_000
        deadline1 = slotToEndPOSIXTime def 5
        deadline2 = slotToEndPOSIXTime def 10

        fp = FirstParams
                { fpSecond         = pkh2
                , fpStake          = stake
                , fpPlayDeadline   = deadline1
                , fpRevealDeadline = deadline2
                , fpNonce          = &quot;SECRETNONCE&quot;
                , fpChoice         = c1
                }

    callEndpoint @&quot;first&quot; h1 fp   -- (1)

    tt &lt;- getTT                   -- (2)

    let sp = SecondParams         -- (3)
                { spFirst          = pkh1
                , spStake          = stake
                , spPlayDeadline   = deadline1
                , spRevealDeadline = deadline2
                , spChoice         = c2
                , spToken          = tt
                }

    void $ Emulator.waitNSlots 3  -- (4)

    callEndpoint @&quot;second&quot; h2 sp

    void $ Emulator.waitNSlots 10
  where
    getTT :: ContractHandle (Last ThreadToken) GameSchema Text -&gt; EmulatorTrace ThreadToken
    getTT h = do
        void $ Emulator.waitNSlots 1
        Last m &lt;- observableState      -- (2)
        case m of
            Nothing -&gt; getTT h
            Just tt -&gt; Extras.logInfo (&quot;read thread token &quot; ++ show tt) &gt;&gt; return tt
</code></pre>
