Skip to content

Commit

Permalink
transfer-contract: add fn transfer_to_account
Browse files Browse the repository at this point in the history
The `transfer_to_account` can be called by contract using the
`TransferToAccount` structure to move some of its funds to a Moonlight
account.
  • Loading branch information
Eduardo Leegwater Simões committed Sep 5, 2024
1 parent 7e9eb62 commit a1440fe
Show file tree
Hide file tree
Showing 3 changed files with 398 additions and 5 deletions.
5 changes: 5 additions & 0 deletions contracts/transfer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ unsafe fn transfer_to_contract(arg_len: u32) -> u32 {
rusk_abi::wrap_call(arg_len, |arg| STATE.transfer_to_contract(arg))
}

#[no_mangle]
unsafe fn transfer_to_account(arg_len: u32) -> u32 {
rusk_abi::wrap_call(arg_len, |arg| STATE.transfer_to_account(arg))
}

// Queries

#[no_mangle]
Expand Down
39 changes: 37 additions & 2 deletions contracts/transfer/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ use execution_core::{
withdraw::{
Withdraw, WithdrawReceiver, WithdrawReplayToken, WithdrawSignature,
},
ReceiveFromContract, Transaction, TransferToContract,
PANIC_NONCE_NOT_READY, TRANSFER_CONTRACT,
ReceiveFromContract, Transaction, TransferToAccount,
TransferToContract, PANIC_NONCE_NOT_READY, TRANSFER_CONTRACT,
},
BlsScalar, ContractError, ContractId,
};
Expand Down Expand Up @@ -352,6 +352,41 @@ impl TransferState {
.expect("Calling receiver should succeed")
}

/// Transfer funds from a contract balance to a Moonlight account.
///
/// Contracts can call the function and expect that if it succeeds the funds
/// are successfully transferred to the account they specify.
///
/// # Panics
/// The function will panic if it is not being called by a contract, if it
/// is called by the transfer contract itself, or if the calling contract
/// doesn't have enough funds.
pub fn transfer_to_account(&mut self, transfer: TransferToAccount) {
let from = rusk_abi::caller()
.expect("A transfer to an account must happen in the context of a transaction");

if from == TRANSFER_CONTRACT {
panic!("Cannot be called directly by the transfer contract");
}

let from_balance = self
.contract_balances
.get_mut(&from)
.expect("Caller must have a balance");

if *from_balance < transfer.value {
panic!("Caller must have enough balance");
}

let account = self
.accounts
.entry(transfer.account.to_bytes())
.or_insert(EMPTY_ACCOUNT);

*from_balance -= transfer.value;
account.balance += transfer.value;
}

/// The top level transaction execution function.
///
/// This will emplace the deposit in the state, if it exists - making it
Expand Down
Loading

0 comments on commit a1440fe

Please sign in to comment.