Skip to content

Commit 510f270

Browse files
authored
Implemented the native XLM transfer logic
1 parent 7e4f317 commit 510f270

5 files changed

Lines changed: 87 additions & 2 deletions

File tree

contracts/ephemeral_account/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ crate-type = ["cdylib", "rlib"]
99
[dependencies]
1010
soroban-sdk = "22.0.0"
1111
bridgelet-shared = { path = "../shared", version = "0.1.0" }
12+
native-transfer = { path = "../native_transfer" }
1213

1314

1415
[dev-dependencies]
1516
soroban-sdk = { version = "22.0.0", features = ["testutils"] }
1617
bridgelet-shared = { path = "../shared", features = ["testutils"] }
18+
native-transfer = { path = "../native_transfer", features = ["testutils"] }
1719

1820
[profile.release]
1921
opt-level = "z"

contracts/ephemeral_account/src/lib.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ mod storage;
77
mod test;
88

99
use soroban_sdk::{contract, contractimpl, Address, BytesN, Env, Vec};
10+
use native_transfer::NativeTransferContractClient as NativeTransferClient;
1011

1112
pub use bridgelet_shared::{AccountInfo, AccountStatus, Payment};
1213
pub use errors::Error;
@@ -37,6 +38,7 @@ impl EphemeralAccountContract {
3738
creator: Address,
3839
expiry_ledger: u32,
3940
recovery_address: Address,
41+
native_transfer_address: Address,
4042
) -> Result<(), Error> {
4143
// Check if already initialized
4244
if storage::is_initialized(&env) {
@@ -58,6 +60,7 @@ impl EphemeralAccountContract {
5860
storage::set_expiry_ledger(&env, expiry_ledger);
5961
storage::set_recovery_address(&env, &recovery_address);
6062
storage::set_status(&env, AccountStatus::Active);
63+
storage::set_native_transfer_address(&env, &native_transfer_address);
6164
storage::init_reserve_tracking(&env, BASE_RESERVE_STROOPS);
6265

6366
// Emit event
@@ -416,6 +419,18 @@ impl EphemeralAccountContract {
416419
Ok(reclaim_amount)
417420
}
418421

422+
// Execute actual native XLM transfer to destination
423+
if reclaim_amount > 0 {
424+
let native_transfer_address = storage::get_native_transfer_address(env)
425+
.ok_or(Error::NotInitialized)?;
426+
let native_client = NativeTransferClient::new(env, &native_transfer_address);
427+
native_client.transfer(
428+
&env.current_contract_address(),
429+
destination,
430+
&reclaim_amount,
431+
);
432+
}
433+
419434
fn emit_and_store_reserve_event(env: &Env, event: ReserveReclaimed) -> Result<(), Error> {
420435
events::emit_reserve_reclaimed(
421436
env,

contracts/ephemeral_account/src/storage.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub enum DataKey {
1717
LastSweepId,
1818
ReserveEventCount,
1919
LastReserveEvent,
20+
NativeTransferAddress,
2021
}
2122

2223
// Initialization
@@ -204,3 +205,15 @@ pub fn set_last_reserve_event(env: &Env, event: &ReserveReclaimed) {
204205
pub fn get_last_reserve_event(env: &Env) -> Option<ReserveReclaimed> {
205206
env.storage().instance().get(&DataKey::LastReserveEvent)
206207
}
208+
209+
pub fn set_native_transfer_address(env: &Env, address: &Address) {
210+
env.storage()
211+
.instance()
212+
.set(&DataKey::NativeTransferAddress, address);
213+
}
214+
215+
pub fn get_native_transfer_address(env: &Env) -> Option<Address> {
216+
env.storage()
217+
.instance()
218+
.get(&DataKey::NativeTransferAddress)
219+
}

contracts/native_transfer/src/errors.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ use soroban_sdk::contracterror;
55
pub enum Error {
66
InvalidAmount = 1,
77
TransferFailed = 2,
8+
AlreadyInitialized = 3,
9+
NotInitialized = 4,
810
}

contracts/native_transfer/src/lib.rs

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
mod errors;
44
mod events;
55

6-
use soroban_sdk::{contract, contractimpl, Env};
6+
use soroban_sdk::{contract, contractimpl, Address, Env};
77

88
pub use errors::Error;
99
pub use events::NativeTransferExecuted;
@@ -13,5 +13,58 @@ pub struct NativeTransferContract;
1313

1414
#[contractimpl]
1515
impl NativeTransferContract {
16-
// Implementation coming in a future issue
16+
/// Initialize with the native asset contract address
17+
///
18+
/// # Arguments
19+
/// * `native_token_address` - The Stellar native XLM token contract address
20+
///
21+
/// # Errors
22+
/// * `Error::AlreadyInitialized` - called more than once
23+
pub fn initialize(env: Env, native_token_address: Address) -> Result<(), Error> {
24+
if env.storage().instance().has(&"native_token") {
25+
return Err(Error::AlreadyInitialized);
26+
}
27+
28+
env.storage()
29+
.instance()
30+
.set(&"native_token", &native_token_address);
31+
32+
Ok(())
33+
}
34+
35+
/// Execute a native XLM transfer
36+
///
37+
/// # Arguments
38+
/// * `from` - Address sending XLM
39+
/// * `to` - Address receiving XLM
40+
/// * `amount` - Amount in stroops (must be positive)
41+
///
42+
/// # Errors
43+
/// * `Error::NotInitialized` - contract not initialized
44+
/// * `Error::InvalidAmount` - amount is zero or negative
45+
pub fn transfer(env: Env, from: Address, to: Address, amount: i128) -> Result<(), Error> {
46+
// Check initialized
47+
let native_token_address: Address = env
48+
.storage()
49+
.instance()
50+
.get(&"native_token")
51+
.ok_or(Error::NotInitialized)?;
52+
53+
// Validate amount
54+
if amount <= 0 {
55+
return Err(Error::InvalidAmount);
56+
}
57+
58+
// Require authorization from sender
59+
from.require_auth();
60+
61+
// Execute transfer via native token client
62+
let native_token = soroban_sdk::token::Client::new(&env, &native_token_address);
63+
native_token.transfer(&from, &to, &amount);
64+
65+
// Emit event
66+
events::emit_native_transfer_executed(&env, from, to, amount);
67+
68+
Ok(())
69+
}
1770
}

0 commit comments

Comments
 (0)