DEV Community

Cover image for Soroban Quest - Reverse Engineer
Altuğ Bakan
Altuğ Bakan

Posted on • Updated on

Soroban Quest - Reverse Engineer

The Auth Store Quest we solved on the last post was quite the feat! We will now tackle the next quest: Reverse Engineer.

Understanding README.md

As always, let's open the README.md file in the 3-reverse-engineer folder and take a look.

README

This quest is quite different! We are tasked with finding the contract ID of the already deployed contract. We have an important tip though, we are given the deployer account's public key, which is GAC7HE4PQWI7H34JQN6QLQ7Y7NTAUZDWJZ4SJ6GXVC4K2DN7N65K5NLI.

The Concept of Public Ledgers

Since we are transacting on a blockchain, all of our transactions are fully inspectable by anyone! Aside from privacy chains (Monero, Zcash, etc.), all of the transactions, meaning contract deployments, coin transfers, account creations are all easily inspectable! This is the case, as the validators should check the integrity of all the data that the blockchain has processed to achieve consensus between all nodes. Of course, there are some other ways such as zk-proofs, which hide the details of the transactions while making them still verifiable!

The so called "privacy" components of the blockchains comes from the idea that we do not know who the public key's owner is. This can be quite handy for privacy, but is also not the exact solution to the privacy problem as the transactions of a user can be mapped to a person with enough information, such as IP addresses, their social media sharings and so on.

Setting Up Our Stellar Quest Account

As always, use sq login if you haven't, and use sq play 2 to start questing. Don't forget to fund your account!

Examining the Contract

Let's check out the lib.rs file in the src folder. The contract is quite short, but has some different concepts than previous contracts. Let's check it out.

pub struct ReverseEngineerContract;

const SECRET : Symbol = symbol!("dancinRaph");

#[contractimpl]
impl ReverseEngineerContract {
    pub fn submit(_: Env, secret: Symbol) -> bool{
        secret == SECRET
    }
}
Enter fullscreen mode Exit fullscreen mode

We see that there is only one function, submit, which takes the argument secret of type Symbol. If you remember, the Symbol type can be thought as a string with a maximum length of 10.

Focus on the following line:

const SECRET : Symbol = symbol!("dancinRaph");
Enter fullscreen mode Exit fullscreen mode

We can see that a constant value is defined here, which is not modifiable by any means using any functions in the contract, or elsewhere. The SECRET constant is also of type Symbol, and has the value of "dancinRaph".

Constants and Secrets in Blockchains

Since the blockchain ledgers are actually public, we can't have secret values by just naming them "SECRET" and not telling anyone. Having the source code of course makes guessing the value trivial, but anyone can reverse engineer any contract's source code, and with some simple bytecode translations, view all of your values.

There are some ways of putting actual secret data on blockchains, such as hashing the values off-chain, and then submitting them. We can also check if another supplied value is correct, we can hash them on-chain, and compare the results. The wonders of cryptography!

Examining the Test

We only have one test function for this quest.

#[test]
fn test_q3() {
    let env = Env::default();
    let contract_id = env.register_contract(None, ReverseEngineerContract);
    let client = ReverseEngineerContractClient::new(&env, &contract_id);

    assert_eq!(client.submit(&symbol!("wrong")), false);
    assert_eq!(client.submit(&SECRET), true);
}
Enter fullscreen mode Exit fullscreen mode

What this test does is quite simple. It checks the output value by giving it a false input, and checks it again by giving it the correct input. We did not expect the contract to panic when we supply an invalid value, as it just simply returns the false value.

Solving the Quest

To even attempt solving the quest, we should first find the contract ID of the quest contract. After finding the contract ID, we should supply the secret keyword that we found as the secret argument of the submit function, and solve the quest.

Stellar Laboratory

The Stellar Laboratory is a place for everything Stellar! You can check out all the endpoints of any Stellar network, even custom ones, and Build, Sign, and Decode transactions!

The Laboratory is definitely a very helpful place, but since we are programmers, and programmers are lazy, we don't want to leave our cozy terminal to solve the quests! Jokes aside, do check out the Stellar Laboratory to learn more about the Horizon API and other Stellar concepts.

Finding the Contract ID

Since the only information we have about the contract is the deployer account, let's check what the deployer account has done on the Futurenet. Let's communicate with the Horizon API from our terminal. Use

curl https://horizon-futurenet.stellar.org/accounts/GAC7HE4PQWI7H34JQN6QLQ7Y7NTAUZDWJZ4SJ6GXVC4K2DN7N65K5NLI/operations
Enter fullscreen mode Exit fullscreen mode

To get some information about the deployer account. The output is quite large, but the interesting part of the JSON response is as follows.

{
  --snip--

  "transaction_successful": true,
  "source_account": "GAC7HE4PQWI7H34JQN6QLQ7Y7NTAUZDWJZ4SJ6GXVC4K2DN7N65K5NLI",

  --snip--

  "transaction_hash": "b4ead070088ad86a32c341907d9944a4f3def6c7f1e42cd6e1789d10ca344c38",

  --snip--

  "function": "HostFunctionHostFnCreateContractWithSourceAccount",
  "footprint": "AAAAAAAAAAEAAAAGTNbD4mfKK1nhwm9oUMF+GpFYPmEFgv/ujOvINx6UVzoAAAADAAAAAw=="
}
Enter fullscreen mode Exit fullscreen mode

We see that the account GAC7HE4PQWI7H34JQN6QLQ7Y7NTAUZDWJZ4SJ6GXVC4K2DN7N65K5NLI has used the function HostFunctionHostFnCreateContractWithSourceAccount, which means that they successfully deployed a contract on the Soroban network. If we inspect the footprint using the soroban CLI, we can get more information about the transaction.

soroban xdr dec \
--type LedgerFootprint \
--xdr AAAAAAAAAAEAAAAGTNbD4mfKK1nhwm9oUMF+GpFYPmEFgv/ujOvINx6UVzoAAAADAAAAAw== \
--output json | grep contractId
Enter fullscreen mode Exit fullscreen mode

We got the contract ID!

Contract ID

XDR Types

eXternal Data Representation (XDR) is a format that is quite compact, reliable, and rich. Stellar ledger uses XDR formatted data to communicate with clients and store all kinds of data. They are shown base64 encoded, which compresses the data even more when communicating with clients. Check out Stellar Docs on XDR for more information.

Invoking the submit Function

Now that we have found the contract ID, we can call the submit function on the ReverseEngineerContract.

soroban invoke \
--id 4cd6c3e267ca2b59e1c26f6850c17e1a91583e610582ffee8cebc8371e94573a \
--fn submit --arg dancinRaph
Enter fullscreen mode Exit fullscreen mode

Submit Function Call

Success! Since we got true as the response, we know that we supplied the correct parameter as an argument. Use sq check 3 to claim your reward 🎉!

Top comments (1)

Collapse
 
altug profile image
Altuğ Bakan • Edited

Hope you enjoyed this post!

If you want to support my work, you can send me some XLM at

GB2M73QXDA7NTXEAQ4T2EGBE7IYMZVUX4GZEOFQKRWJEMC2AVHRYL55V
Stellar Wallet

Thanks for all your support!