Skip to content

Commit

Permalink
tranfer-contract: add check for wrong target contract in conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
Eduardo Leegwater Simões committed Jul 26, 2024
1 parent aedbb74 commit 16b32eb
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 14 deletions.
3 changes: 3 additions & 0 deletions contracts/transfer/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ impl TransferState {
if rusk_abi::caller() != TRANSFER_CONTRACT {
panic!("Only a direct call can be a conversion");
}
if *convert.contract() != TRANSFER_CONTRACT.to_bytes() {
panic!("The conversion must target the transfer contract");
}

let deposit = transitory::deposit_info_mut();
match deposit {
Expand Down
7 changes: 4 additions & 3 deletions contracts/transfer/tests/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ use execution_core::{
Note, PublicKey, SchnorrSecretKey, SecretKey, Sender, TxSkeleton, ViewKey,
};
use rusk_abi::{
ContractError, ContractId, PiecrustError, Session, TRANSFER_CONTRACT,
CallReceipt, ContractError, ContractId, PiecrustError, Session,
TRANSFER_CONTRACT,
};

use dusk_bytes::Serializable;
Expand Down Expand Up @@ -143,7 +144,7 @@ pub fn prover_verifier(input_notes: usize) -> (Prover, Verifier) {
pub fn execute(
session: &mut Session,
tx: impl Into<Transaction>,
) -> Result<u64, PiecrustError> {
) -> Result<CallReceipt<Result<Vec<u8>, ContractError>>, PiecrustError> {
let tx = tx.into();

let mut receipt = session.call::<_, Result<Vec<u8>, ContractError>>(
Expand All @@ -169,7 +170,7 @@ pub fn execute(

receipt.events.extend(refund_receipt.events);

Ok(receipt.gas_spent)
Ok(receipt)
}

/// Returns vector of notes owned by a given view key.
Expand Down
130 changes: 119 additions & 11 deletions contracts/transfer/tests/transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,9 @@ fn phoenix_transfer() {
contract_call,
);

let gas_spent = execute(session, tx).expect("Executing TX should succeed");
let gas_spent = execute(session, tx)
.expect("Executing TX should succeed")
.gas_spent;
update_root(session).expect("Updating the root should succeed");

println!("EXECUTE_1_2 : {} gas", gas_spent);
Expand Down Expand Up @@ -260,8 +262,9 @@ fn moonlight_transfer() {
None::<ContractExec>,
);

let gas_spent =
execute(session, transaction).expect("Transaction should succeed");
let gas_spent = execute(session, transaction)
.expect("Transaction should succeed")
.gas_spent;

println!("MOONLIGHT TRANSFER: {} gas", gas_spent);

Expand Down Expand Up @@ -329,7 +332,9 @@ fn phoenix_alice_ping() {
contract_call,
);

let gas_spent = execute(session, tx).expect("Executing TX should succeed");
let gas_spent = execute(session, tx)
.expect("Executing TX should succeed")
.gas_spent;
update_root(session).expect("Updating the root should succeed");

println!("EXECUTE_PING: {} gas", gas_spent);
Expand Down Expand Up @@ -384,8 +389,9 @@ fn moonlight_alice_ping() {
contract_call,
);

let gas_spent =
execute(session, transaction).expect("Transaction should succeed");
let gas_spent = execute(session, transaction)
.expect("Transaction should succeed")
.gas_spent;

println!("MOONLIGHT PING: {} gas", gas_spent);

Expand Down Expand Up @@ -449,8 +455,9 @@ fn phoenix_deposit_and_withdraw() {
contract_call,
);

let gas_spent =
execute(session, tx.clone()).expect("Executing TX should succeed");
let gas_spent = execute(session, tx.clone())
.expect("Executing TX should succeed")
.gas_spent;
update_root(session).expect("Updating the root should succeed");

println!("EXECUTE_DEPOSIT: {} gas", gas_spent);
Expand Down Expand Up @@ -541,7 +548,9 @@ fn phoenix_deposit_and_withdraw() {
contract_call,
);

let gas_spent = execute(session, tx).expect("Executing TX should succeed");
let gas_spent = execute(session, tx)
.expect("Executing TX should succeed")
.gas_spent;
update_root(session).expect("Updating the root should succeed");

println!("EXECUTE_WITHDRAW: {} gas", gas_spent);
Expand Down Expand Up @@ -618,7 +627,9 @@ fn phoenix_to_moonlight_swap() {
Some(contract_call),
);

let gas_spent = execute(session, tx).expect("Executing TX should succeed");
let gas_spent = execute(session, tx)
.expect("Executing TX should succeed")
.gas_spent;
update_root(session).expect("Updating the root should succeed");

println!("CONVERT phoenix to moonlight: {} gas", gas_spent);
Expand Down Expand Up @@ -714,7 +725,8 @@ fn moonlight_to_phoenix_swap() {
);

let gas_spent = execute(&mut session, tx)
.expect("Executing transaction should succeed");
.expect("Executing transaction should succeed")
.gas_spent;
update_root(session).expect("Updating the root should succeed");

println!("CONVERT moonlight to phoenix: {} gas", gas_spent);
Expand All @@ -737,3 +749,99 @@ fn moonlight_to_phoenix_swap() {

assert_eq!(notes.len(), 1, "A new note should have been created");
}

#[test]
fn swap_wrong_contract_targeted() {
const SWAP_VALUE: u64 = dusk(1.0);

let rng = &mut StdRng::seed_from_u64(0xfeeb);

let phoenix_sk = SecretKey::random(rng);
let phoenix_vk = ViewKey::from(&phoenix_sk);
let phoenix_pk = PublicKey::from(&phoenix_sk);

let moonlight_sk = BlsSecretKey::random(rng);
let moonlight_pk = BlsPublicKey::from(&moonlight_sk);

let vm = &mut rusk_abi::new_ephemeral_vm()
.expect("Creating ephemeral VM should work");
let mut session = &mut instantiate(rng, vm, &phoenix_pk, &moonlight_pk);

let swapper_account = account(&mut session, &moonlight_pk)
.expect("Getting account should succeed");
let nonce = swapper_account.nonce + 1;

assert_eq!(
swapper_account.balance, MOONLIGHT_GENESIS_VALUE,
"The swapper's account should have the genesis value"
);

let leaves = leaves_from_height(session, 1)
.expect("getting the notes should succeed");
let notes = filter_notes_owned_by(
phoenix_vk,
leaves.into_iter().map(|leaf| leaf.note),
);

assert_eq!(notes.len(), 0, "There should be no notes at this height");

let address =
phoenix_pk.gen_stealth_address(&JubJubScalar::random(&mut *rng));
let note_sk = phoenix_sk.gen_note_sk(&address);

let convert = Withdraw::new(
rng,
&note_sk,
ALICE_ID.to_bytes(), /* this should be the transfer contract, but
* we're testing the "wrong target" case */
SWAP_VALUE,
WithdrawReceiver::Phoenix(address),
WithdrawReplayToken::Moonlight(nonce),
);

let contract_call = ContractCall {
contract: TRANSFER_CONTRACT.to_bytes(),
fn_name: String::from("convert"),
fn_args: rkyv::to_bytes::<_, 1024>(&convert)
.expect("should serialize conversion correctly")
.to_vec(),
};

let tx = create_moonlight_transaction(
&moonlight_sk,
None,
0,
SWAP_VALUE,
GAS_LIMIT,
LUX,
nonce,
Some(contract_call),
);

let receipt = execute(&mut session, tx)
.expect("Executing transaction should succeed");
update_root(session).expect("Updating the root should succeed");

let res = receipt.data;
let gas_spent = receipt.gas_spent;

assert!(matches!(res, Err(_)), "The contract call should error");

let swapper_account = account(&mut session, &moonlight_pk)
.expect("Getting account should succeed");

assert_eq!(
swapper_account.balance,
MOONLIGHT_GENESIS_VALUE - gas_spent,
"The swapper's account should have only the gas spent subtracted"
);

let leaves = leaves_from_height(session, 1)
.expect("getting the notes should succeed");
let notes = filter_notes_owned_by(
phoenix_vk,
leaves.into_iter().map(|leaf| leaf.note),
);

assert!(notes.is_empty(), "A new note should not been created");
}

0 comments on commit 16b32eb

Please sign in to comment.