Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: escrow transfers #808

Merged
merged 4 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions locked-asset/lkmex-transfer/src/energy_transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ pub trait EnergyTransferModule:
let epoch_diff = current_epoch - attributes.unlock_epoch;
let simulated_deplete_amount = &token.amount * epoch_diff;
energy.remove_energy_raw(BigUint::zero(), simulated_deplete_amount);
energy.add_energy_raw(token.amount, BigInt::zero());
}
}

Expand Down
197 changes: 197 additions & 0 deletions locked-asset/lkmex-transfer/tests/lkmex_transfer_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -621,3 +621,200 @@ fn cancel_transfer_test() {
})
.assert_ok();
}

#[test]
fn transfer_locked_token_after_unlock_period_test() {
let rust_zero = rust_biguint!(0);
let mut b_mock = BlockchainStateWrapper::new();

let user_addr = b_mock.create_user_account(&rust_zero);
let claimer_addr = b_mock.create_user_account(&rust_zero);
let owner_addr = b_mock.create_user_account(&rust_zero);
let transfer_sc_wrapper = b_mock.create_sc_account(
&rust_zero,
Some(&owner_addr),
lkmex_transfer::contract_obj,
"Some path",
);
let factory_sc_wrapper = b_mock.create_sc_account(
&rust_zero,
Some(&owner_addr),
energy_factory::contract_obj,
"Some other path",
);

b_mock.set_block_epoch(5);

// Setup transfer SC
b_mock
.execute_tx(&owner_addr, &transfer_sc_wrapper, &rust_zero, |sc| {
sc.init(
managed_address!(factory_sc_wrapper.address_ref()),
managed_token_id!(LOCKED_TOKEN_ID),
4,
EPOCHS_IN_YEAR,
);
})
.assert_ok();

b_mock.set_esdt_local_roles(
transfer_sc_wrapper.address_ref(),
LOCKED_TOKEN_ID,
&[EsdtLocalRole::Transfer],
);

// setup energy factory SC
b_mock
.execute_tx(&owner_addr, &factory_sc_wrapper, &rust_zero, |sc| {
let mut lock_options = MultiValueEncoded::new();
for (option, penalty) in LOCK_OPTIONS.iter().zip(PENALTY_PERCENTAGES.iter()) {
lock_options.push((*option, *penalty).into());
}

// sc addresses don't matter here, we don't test that part
sc.init(
managed_token_id!(BASE_ASSET_TOKEN_ID),
managed_token_id!(LEGACY_LOCKED_TOKEN_ID),
managed_address!(transfer_sc_wrapper.address_ref()),
0,
lock_options,
);

sc.locked_token()
.set_token_id(managed_token_id!(LOCKED_TOKEN_ID));
sc.token_transfer_whitelist()
.add(&managed_address!(transfer_sc_wrapper.address_ref()));
sc.set_paused(false);
})
.assert_ok();

b_mock.set_esdt_local_roles(
factory_sc_wrapper.address_ref(),
BASE_ASSET_TOKEN_ID,
&[EsdtLocalRole::Mint, EsdtLocalRole::Burn],
);
b_mock.set_esdt_local_roles(
factory_sc_wrapper.address_ref(),
LOCKED_TOKEN_ID,
&[
EsdtLocalRole::NftCreate,
EsdtLocalRole::NftAddQuantity,
EsdtLocalRole::NftBurn,
EsdtLocalRole::Transfer,
],
);
b_mock.set_esdt_local_roles(
factory_sc_wrapper.address_ref(),
LEGACY_LOCKED_TOKEN_ID,
&[EsdtLocalRole::NftBurn],
);

// setup user balance

b_mock.set_esdt_balance(
&user_addr,
BASE_ASSET_TOKEN_ID,
&rust_biguint!(USER_BALANCE),
);

// lock tokens
b_mock
.execute_esdt_transfer(
&user_addr,
&factory_sc_wrapper,
BASE_ASSET_TOKEN_ID,
0,
&rust_biguint!(USER_BALANCE),
|sc| {
sc.lock_tokens_endpoint(LOCK_OPTIONS[0], OptionalValue::None);

let unlock_epoch = sc.unlock_epoch_to_start_of_month(5 + LOCK_OPTIONS[0]);
let lock_epochs = unlock_epoch - 5;
let expected_energy_amount =
BigInt::from(USER_BALANCE as i64) * BigInt::from(lock_epochs as i64);
let expected_energy =
Energy::new(expected_energy_amount, 5, managed_biguint!(USER_BALANCE));
let actual_energy = sc.user_energy(&managed_address!(&user_addr)).get();
assert_eq!(expected_energy, actual_energy);
},
)
.assert_ok();

// transfer half of the LKMEX to other user
b_mock
.execute_esdt_transfer(
&user_addr,
&transfer_sc_wrapper,
LOCKED_TOKEN_ID,
1,
&rust_biguint!(USER_BALANCE / 2),
|sc| {
sc.lock_funds(managed_address!(&claimer_addr));
},
)
.assert_ok();

// check first user energy after transfer
b_mock
.execute_query(&factory_sc_wrapper, |sc| {
let unlock_epoch = sc.unlock_epoch_to_start_of_month(5 + LOCK_OPTIONS[0]);
let lock_epochs = unlock_epoch - 5;
let expected_energy_amount =
BigInt::from((USER_BALANCE / 2) as i64) * BigInt::from(lock_epochs as i64);
let expected_energy = Energy::new(
expected_energy_amount,
5,
managed_biguint!(USER_BALANCE / 2),
);
let actual_energy = sc.user_energy(&managed_address!(&user_addr)).get();
assert_eq!(expected_energy, actual_energy);
})
.assert_ok();

let current_epoch = EPOCHS_IN_YEAR + 3;
// pass 5 epochs
b_mock.set_block_epoch(current_epoch);

// second user claim
b_mock
.execute_tx(&claimer_addr, &transfer_sc_wrapper, &rust_zero, |sc| {
sc.withdraw(managed_address!(&user_addr));
})
.assert_ok();

// check first user energy
b_mock
.execute_query(&factory_sc_wrapper, |sc| {
let unlock_epoch = sc.unlock_epoch_to_start_of_month(5 + LOCK_OPTIONS[0]);
let lock_epochs = unlock_epoch as i64 - current_epoch as i64;
let expected_energy_amount =
BigInt::from((USER_BALANCE / 2) as i64) * BigInt::from(lock_epochs);
let expected_energy = Energy::new(
expected_energy_amount,
current_epoch,
managed_biguint!(USER_BALANCE / 2),
);

let actual_energy = sc.user_energy(&managed_address!(&claimer_addr)).get();
assert_eq!(expected_energy, actual_energy);
})
.assert_ok();

// check second user energy
b_mock
.execute_query(&factory_sc_wrapper, |sc| {
let unlock_epoch = sc.unlock_epoch_to_start_of_month(5 + LOCK_OPTIONS[0]);
let lock_epochs = unlock_epoch as i64 - current_epoch as i64;
let expected_energy_amount =
BigInt::from((USER_BALANCE / 2) as i64) * BigInt::from(lock_epochs);
let expected_energy = Energy::new(
expected_energy_amount,
current_epoch,
managed_biguint!(USER_BALANCE / 2),
);

let actual_energy = sc.user_energy(&managed_address!(&claimer_addr)).get();
assert_eq!(expected_energy, actual_energy);
})
.assert_ok();
}