Skip to content

Implement scaffold transceiver core contract and placeholder NTT manager#3

Open
cupicmarko wants to merge 2 commits intostellarfrom
feature/stellar-transceiver
Open

Implement scaffold transceiver core contract and placeholder NTT manager#3
cupicmarko wants to merge 2 commits intostellarfrom
feature/stellar-transceiver

Conversation

@cupicmarko
Copy link
Copy Markdown

@cupicmarko cupicmarko commented Dec 2, 2025

Implements not-yet complete Wormhole transceiver for Soroban contracts.

@cupicmarko cupicmarko requested review from Oghma and dkgoutham December 2, 2025 11:52
@cupicmarko cupicmarko marked this pull request as ready for review December 4, 2025 09:08
Copy link
Copy Markdown
Collaborator

@Oghma Oghma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a good starting point. I left some notes.
In the next PRs we have to

  • remove all the panics
  • use bytesreader lib from WormholeInterface
  • Add errors
  • Add the interfaces
  • Polishing the code

[package]
name = "stellar-ntt-manager"
version = "0.1.0"
edition = "2021"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use the workspace version instead?


fn read_u32_be(msg: &Bytes, offset: u32) -> u32 {
// TODO: Move to other repo if it makes sense
let b0 = msg
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think of this version?

    let end = offset.checked_add(4).expect("offset overflow");

    if msg.len() > end {
        panic!("message too short");
    }

    let mut buf = [0u8; 4];
    msg.slice(offset..end).copy_into_slice(&mut buf);
    u32::from_be_bytes(buf)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or even

let end = offset.checked_add(4).expect("offset overflow");
u32::from_be_bytes(
        msg.slice(offset..end)
            .try_into()
            .expect("message too short"),
    )

let mut out = Bytes::new(env);

// Layout is: prefix || source_manager || recipient_manager || manager_payload
out.append(&Bytes::from_array(env, &NTT_PREFIX.to_be_bytes()));
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

    out.extend_from_slice(&NTT_PREFIX.to_be_bytes());
    out.extend_from_slice(&source_manager.to_array());
    out.extend_from_slice(&recipient_manager.to_array());

So we avoid to create an array


fn read_32_bytes(msg: &Bytes, offset: u32) -> [u8; 32] {
// TODO: Move to other repo if it makes sense
let mut out = [0u8; 32];
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as read_u32_be

    let end = offset.checked_add(4).expect("offset overflow");

    msg.slice(offset..end)
        .try_into()
        .expect("message too short")

args.push_back(consistency.into_val(&env));

let res: Result<u64, WormholeError> =
env.invoke_contract(&core_addr, &Symbol::new(&env, "post_message"), args);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not instantiate a WormholeInterfaceClient and call post_message?

verify_args.push_back(vaa_bytes.into_val(&env));

let verified: Result<bool, WormholeError> =
env.invoke_contract(&core_addr, &Symbol::new(&env, "verify_vaa"), verify_args);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initialize a WormholeCoreClient instead

const KEY_MANAGER_ID: &str = "mi";
const KEY_CONSUMED: &str = "c";

fn init_key(env: &Env) -> Symbol {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I remember correctly, there are macros for doing that. I mean, as a const

}));
assert!(res.is_err());

use alloc::string::String;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You already defined at line 385. When we have Result implemented, we can delete it.

env.storage().instance().set(&key, &true);
}

#[cfg(test)]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move to test.rs?

@@ -0,0 +1,857 @@
#![no_std]
extern crate alloc;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's necessary. Or, if necessary, only the tests require it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants