RPCIEGE - Skirmish 10

Row-Bear - Oct 6 '23 - - Dev Community

And we're already moving on to Skirmish 10 of the RPCiege!

Have a look at the booklet for the exact details of the mission. Here's my summary:

  • We have been given a game contract, and its code
  • To complete the skirmish, we have to guess an "unpredictable" number, and invoke the contract with that number as parameter.
  • Since we have the code, the number is not exactly unpredictable. We just have to extract it.

As a small diversion, you can try to make a manual guess.
After all, you have about 1 in 4 billion chance to guess correct.

Image description
Okay, that's not going to work. We'll have to look at the contracts code.

Image description

The magic happens in this part of the code:

let state = u64::MIN
    .wrapping_add(env.ledger().timestamp())
    .wrapping_add(env.ledger().sequence() as u64);
let mut rng = SmallRng::seed_from_u64(state);

if guess != rng.gen_range(0..1_000_000_000) {
    return Err(Error::WrongGuess);
}
Enter fullscreen mode Exit fullscreen mode

We see that a random number is derived from the ledger timestamp and ledger sequence.
Then, our guess is compared to that number.
Back in Skirmish 6 there was a similar situation. Then, there was some room to calculate the number, then quickly invoke the game contract.

Now, we don't have that option. We have to make the guess in the same ledger as the calculation happens.
Luckily, cross-contract calls come to the rescue.
If your contract calls another contract, that will happen in the same ledger.
So, we can make our own contract and use the same logic to calculate the guess. Then call the game contract from our own contract, and since it happens in the same ledger, the timestamp and sequence will be the same.

The Soroban Examples include a cross-contract example, which I've used as the basis for the solution.
Like the in previous skirmish, we can use soroban contract fetch in soroban-cli to retreive the game contract.

Then, it can be imported in your own contract code, so you can interact with it.
Image description

I'm not going to give out the full solution, but I'll share my wrong_guess function.
Image description
It sets my guess to 1, then calls the target contract with it.
Notice how I've put a target: Address parameter in the contract.
When invoking my contract, I have to put the game contract in as argument. That way, my contract knows which contract to shoot the guess at.

Now it's up to you to replace let guess: u32 = 1; with the calculation for the correct number. With the information above and in the booklet, you should be able to :-)
And if not, leave a comment, or even better, hop in the Stellar Dev Discord.

Happy cieging!

Row-Bear

PS: If you get stuck, chances are you'll have to add a dependency or two to your Cargo.toml:

[dependencies]
soroban-sdk = "20.0.0-rc2"
rand = { version = "0.8.5", default-features = false, features = ["small_rng"] }
getrandom = { version = "0.2", features = ["js"] }
Enter fullscreen mode Exit fullscreen mode
. . . . . . .