Skip to content

Commit 2559ed6

Browse files
authored
feat: add simple call (#91)
1 parent 24eb902 commit 2559ed6

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

programs/gateway/src/lib.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,28 @@ pub mod gateway {
666666
Ok(())
667667
}
668668

669+
/// Calls a contract on ZetaChain zEVM.
670+
///
671+
/// # Arguments
672+
/// * `ctx` - The instruction context.
673+
/// * `receiver` - The Ethereum address of the receiver on ZetaChain zEVM.
674+
/// * `message` - The message passed to the contract.
675+
pub fn call(_ctx: Context<Call>, receiver: [u8; 20], message: Vec<u8>) -> Result<()> {
676+
require!(receiver != [0u8; 20], Errors::EmptyReceiver);
677+
require!(
678+
message.len() <= MAX_DEPOSIT_PAYLOAD_SIZE,
679+
Errors::MemoLengthExceeded
680+
);
681+
682+
msg!(
683+
"Call executed: receiver = {:?}, message = {:?}",
684+
receiver,
685+
message
686+
);
687+
688+
Ok(())
689+
}
690+
669691
/// Withdraws SOL. Caller is TSS.
670692
///
671693
/// # Arguments
@@ -1058,6 +1080,14 @@ pub struct DepositSplToken<'info> {
10581080
pub system_program: Program<'info, System>,
10591081
}
10601082

1083+
/// Instruction context for call operation.
1084+
#[derive(Accounts)]
1085+
pub struct Call<'info> {
1086+
/// The account of the signer making the call.
1087+
#[account(mut)]
1088+
pub signer: Signer<'info>,
1089+
}
1090+
10611091
/// Instruction context for SOL withdrawal operations.
10621092
#[derive(Accounts)]
10631093
pub struct Withdraw<'info> {

tests/gateway.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1888,6 +1888,43 @@ describe("Gateway", () => {
18881888
}
18891889
});
18901890

1891+
it("Call with empty address receiver should fail", async () => {
1892+
try {
1893+
await gatewayProgram.methods
1894+
.call(Array(20).fill(0), Buffer.from("hello", "utf-8"))
1895+
.rpc();
1896+
throw new Error("Expected error not thrown");
1897+
} catch (err) {
1898+
expect(err).to.be.instanceof(anchor.AnchorError);
1899+
expect(err.message).to.include("EmptyReceiver");
1900+
}
1901+
});
1902+
1903+
it("Call with above max payload size should fail", async () => {
1904+
try {
1905+
await gatewayProgram.methods
1906+
.call(
1907+
Array.from(address),
1908+
Buffer.from(Array(maxPayloadSize + 1).fill(1))
1909+
)
1910+
.rpc();
1911+
throw new Error("Expected error not thrown");
1912+
} catch (err) {
1913+
expect(err).to.be.instanceof(anchor.AnchorError);
1914+
expect(err.message).to.include("MemoLengthExceeded");
1915+
}
1916+
});
1917+
1918+
it("Call with max payload size", async () => {
1919+
const txsig = await gatewayProgram.methods
1920+
.call(Array.from(address), Buffer.from(Array(maxPayloadSize).fill(1)))
1921+
.preInstructions([
1922+
ComputeBudgetProgram.setComputeUnitLimit({ units: 400000 }),
1923+
])
1924+
.rpc({ commitment: "processed" });
1925+
await conn.getParsedTransaction(txsig, "confirmed");
1926+
});
1927+
18911928
it("Deposit and call with max payload size", async () => {
18921929
const bal1 = await conn.getBalance(pdaAccount);
18931930
const txsig = await gatewayProgram.methods

0 commit comments

Comments
 (0)