From d0ed05a3ddd05fd4f25729b0016a9b1644b7eef2 Mon Sep 17 00:00:00 2001 From: Charlotte Date: Wed, 2 Oct 2024 09:52:58 +0800 Subject: [PATCH] test withdraw liquidity --- .../contracts/ramps/revolut/interface.cairo | 2 +- .../ramps/revolut/revolut_test.cairo | 247 ++++++++++++++++-- 2 files changed, 230 insertions(+), 19 deletions(-) diff --git a/contracts/src/contracts/ramps/revolut/interface.cairo b/contracts/src/contracts/ramps/revolut/interface.cairo index 1f93846..409bdc3 100644 --- a/contracts/src/contracts/ramps/revolut/interface.cairo +++ b/contracts/src/contracts/ramps/revolut/interface.cairo @@ -7,7 +7,7 @@ use zkramp::components::registry::interface::OffchainId; #[derive(Drop, Serde)] pub struct Proof { - foo: felt252 + pub foo: felt252 } #[derive(Drop, Copy, Hash, Serde, starknet::Store)] diff --git a/contracts/src/contracts/ramps/revolut/revolut_test.cairo b/contracts/src/contracts/ramps/revolut/revolut_test.cairo index 949e09b..c3965c3 100644 --- a/contracts/src/contracts/ramps/revolut/revolut_test.cairo +++ b/contracts/src/contracts/ramps/revolut/revolut_test.cairo @@ -6,9 +6,10 @@ use snforge_std::{ EventSpyAssertionsTrait, spy_events, declare, DeclareResultTrait, ContractClassTrait, start_cheat_caller_address, stop_cheat_caller_address, test_address, start_cheat_block_timestamp_global }; -use zkramp::contracts::ramps::revolut::interface::{ZKRampABIDispatcher, ZKRampABIDispatcherTrait, LiquidityKey}; +use zkramp::contracts::ramps::revolut::interface::{ZKRampABIDispatcher, ZKRampABIDispatcherTrait, LiquidityKey, Proof}; use zkramp::contracts::ramps::revolut::revolut::RevolutRamp::{ - Event, LiquidityAdded, LiquidityRetrieved, LiquidityLocked, LiquidityShareRequested, MINIMUM_LOCK_DURATION + Event, LiquidityAdded, LiquidityRetrieved, LiquidityLocked, LiquidityShareRequested, LiquidityShareWithdrawn, + MINIMUM_LOCK_DURATION }; use zkramp::tests::constants; use zkramp::tests::utils; @@ -914,39 +915,249 @@ fn test_initiate_liquidity_withdraw_twice() { revolut_ramp.initiate_liquidity_withdrawal(:liquidity_key, amount: amount2, offchain_id: withdrawer_offchain_id); } -// #[test] -// #[should_panic(expected: 'Liquidity share not available')] +#[test] +#[should_panic(expected: 'Liquidity share not available')] fn test_withdraw_liquidity_without_request() { - panic!("Not implemented yet"); + let (revolut_ramp, erc20) = setup(); + + // off-ramper + let liquidity_owner = constants::CALLER(); + let offchain_id = constants::REVOLUT_ID(); + let amount = 42; + + // on-ramper + let withdrawer = constants::OTHER(); + let withdrawer_offchain_id = constants::REVOLUT_ID2(); + let liquidity_key = LiquidityKey { owner: liquidity_owner, offchain_id }; + let proof = Proof { foo: 0 }; + + // fund the account + fund_and_approve(token: erc20, recipient: liquidity_owner, spender: revolut_ramp.contract_address, amount: amount); + + // register offchain ID + start_cheat_caller_address(revolut_ramp.contract_address, liquidity_owner); + revolut_ramp.register(:offchain_id); + + // add liquidity + revolut_ramp.add_liquidity(:amount, :offchain_id); + + // withdrawer tries to withdraw + start_cheat_caller_address(revolut_ramp.contract_address, withdrawer); + revolut_ramp.register(offchain_id: withdrawer_offchain_id); + revolut_ramp.withdraw_liquidity(:liquidity_key, offchain_id: withdrawer_offchain_id, :proof); } -// #[test] -// #[should_panic(expected: 'Liquidity share not available')] +#[test] +#[should_panic(expected: 'Liquidity share not available')] fn test_withdraw_liquidity_after_expiration() { - panic!("Not implemented yet"); + let (revolut_ramp, erc20) = setup(); + + // off-ramper + let liquidity_owner = constants::CALLER(); + let offchain_id = constants::REVOLUT_ID(); + let amount = 42; + + // on-ramper + let withdrawer = constants::OTHER(); + let withdrawer_offchain_id = constants::REVOLUT_ID2(); + let liquidity_key = LiquidityKey { owner: liquidity_owner, offchain_id }; + let proof = Proof { foo: 0 }; + + // fund the account + fund_and_approve(token: erc20, recipient: liquidity_owner, spender: revolut_ramp.contract_address, amount: amount); + + // register offchain ID + start_cheat_caller_address(revolut_ramp.contract_address, liquidity_owner); + revolut_ramp.register(:offchain_id); + + // add liquidity + revolut_ramp.add_liquidity(:amount, :offchain_id); + + // withdrawer initiates withdrawal + start_cheat_caller_address(revolut_ramp.contract_address, withdrawer); + revolut_ramp.register(offchain_id: withdrawer_offchain_id); + revolut_ramp.initiate_liquidity_withdrawal(:liquidity_key, :amount, offchain_id: withdrawer_offchain_id); + + // offer expires + start_cheat_block_timestamp_global(MINIMUM_LOCK_DURATION); + + // withdrawer withdraws + revolut_ramp.withdraw_liquidity(:liquidity_key, offchain_id: withdrawer_offchain_id, :proof); } -// #[test] -// #[should_panic(expected: 'Liquidity share not available')] +#[test] +#[should_panic(expected: 'Liquidity share not available')] fn test_withdraw_liquidity_from_another_caller() { - panic!("Not implemented yet"); + let (revolut_ramp, erc20) = setup(); + + // off-ramper + let liquidity_owner = constants::CALLER(); + let offchain_id = constants::REVOLUT_ID(); + let amount = 42; + + // on-ramper + let withdrawer = constants::OTHER(); + let withdrawer_offchain_id = constants::REVOLUT_ID2(); + let liquidity_key = LiquidityKey { owner: liquidity_owner, offchain_id }; + let proof = Proof { foo: 0 }; + + // other on-ramper + let other_withdrawer = constants::OTHER2(); + + // fund the account + fund_and_approve(token: erc20, recipient: liquidity_owner, spender: revolut_ramp.contract_address, amount: amount); + + // register offchain ID + start_cheat_caller_address(revolut_ramp.contract_address, liquidity_owner); + revolut_ramp.register(:offchain_id); + + // add liquidity + revolut_ramp.add_liquidity(:amount, :offchain_id); + + // withdrawer initiates withdrawal + start_cheat_caller_address(revolut_ramp.contract_address, withdrawer); + revolut_ramp.register(offchain_id: withdrawer_offchain_id); + revolut_ramp.initiate_liquidity_withdrawal(:liquidity_key, :amount, offchain_id: withdrawer_offchain_id); + + // other caller tries to withdraw + start_cheat_caller_address(revolut_ramp.contract_address, other_withdrawer); + revolut_ramp.withdraw_liquidity(:liquidity_key, offchain_id: offchain_id, :proof); } -// #[test] -// #[should_panic(expected: 'Liquidity share not available')] +#[test] +#[should_panic(expected: 'Liquidity share not available')] fn test_withdraw_liquidity_from_another_offchain_id() { + let (revolut_ramp, erc20) = setup(); + + // off-ramper + let liquidity_owner = constants::CALLER(); + let offchain_id = constants::REVOLUT_ID(); + let amount = 42; + + // on-ramper + let withdrawer = constants::OTHER(); + let withdrawer_offchain_id = constants::REVOLUT_ID2(); + let liquidity_key = LiquidityKey { owner: liquidity_owner, offchain_id }; + let proof = Proof { foo: 0 }; + + // other on-ramper + let other_withdrawer_offchain_id = constants::REVOLUT_ID3(); + + // fund the account + fund_and_approve(token: erc20, recipient: liquidity_owner, spender: revolut_ramp.contract_address, amount: amount); + + // register offchain ID + start_cheat_caller_address(revolut_ramp.contract_address, liquidity_owner); + revolut_ramp.register(:offchain_id); + + // add liquidity + revolut_ramp.add_liquidity(:amount, :offchain_id); + + // withdrawer initiates withdrawal + start_cheat_caller_address(revolut_ramp.contract_address, withdrawer); + revolut_ramp.register(offchain_id: withdrawer_offchain_id); + revolut_ramp.initiate_liquidity_withdrawal(:liquidity_key, :amount, offchain_id: withdrawer_offchain_id); + + // other offchain-id tries to withdraw + revolut_ramp.withdraw_liquidity(:liquidity_key, offchain_id: other_withdrawer_offchain_id, :proof); panic!("Not implemented yet"); } -// #[test] +#[test] fn test_withdraw_liquidity() { - panic!("Not implemented yet"); + let (revolut_ramp, erc20) = setup(); + let mut spy = spy_events(); + + // off-ramper + let liquidity_owner = constants::CALLER(); + let offchain_id = constants::REVOLUT_ID(); + let amount = 42; + + // on-ramper + let withdrawer = constants::OTHER(); + let withdrawer_offchain_id = constants::REVOLUT_ID2(); + let liquidity_key = LiquidityKey { owner: liquidity_owner, offchain_id }; + let proof = Proof { foo: 0 }; + + // fund the account + fund_and_approve(token: erc20, recipient: liquidity_owner, spender: revolut_ramp.contract_address, amount: amount); + + // register offchain ID + start_cheat_caller_address(revolut_ramp.contract_address, liquidity_owner); + revolut_ramp.register(:offchain_id); + + // add liquidity + revolut_ramp.add_liquidity(:amount, :offchain_id); + + // assert state before + assert_eq!(revolut_ramp.all_liquidity(:liquidity_key), amount); + assert_eq!(revolut_ramp.available_liquidity(:liquidity_key), amount); + assert_eq!(erc20.balance_of(withdrawer), 0); + + // withdrawer initiates withdrawal + start_cheat_caller_address(revolut_ramp.contract_address, withdrawer); + revolut_ramp.register(offchain_id: withdrawer_offchain_id); + revolut_ramp.initiate_liquidity_withdrawal(:liquidity_key, :amount, offchain_id: withdrawer_offchain_id); + + // withdrawer withdraws + revolut_ramp.withdraw_liquidity(:liquidity_key, offchain_id: withdrawer_offchain_id, :proof); + + // assert state after + assert_eq!(revolut_ramp.all_liquidity(:liquidity_key), 0); + assert_eq!(revolut_ramp.available_liquidity(:liquidity_key), 0); + assert_eq!(erc20.balance_of(withdrawer), amount); + + // check on emitted events + spy + .assert_emitted( + @array![ + ( + revolut_ramp.contract_address, + Event::LiquidityShareWithdrawn( + LiquidityShareWithdrawn { + liquidity_key, amount, withdrawer, offchain_id: withdrawer_offchain_id, + } + ) + ) + ] + ) } -// #[test] -// #[should_panic(expected: 'Liquidity share not available')] +#[test] +#[should_panic(expected: 'Liquidity share not available')] fn test_withdraw_liquidity_twice() { - panic!("Not implemented yet"); + let (revolut_ramp, erc20) = setup(); + + // off-ramper + let liquidity_owner = constants::CALLER(); + let offchain_id = constants::REVOLUT_ID(); + let amount = 42; + + // on-ramper + let withdrawer = constants::OTHER(); + let withdrawer_offchain_id = constants::REVOLUT_ID2(); + let liquidity_key = LiquidityKey { owner: liquidity_owner, offchain_id }; + + // fund the account + fund_and_approve(token: erc20, recipient: liquidity_owner, spender: revolut_ramp.contract_address, amount: amount); + + // register offchain ID + start_cheat_caller_address(revolut_ramp.contract_address, liquidity_owner); + revolut_ramp.register(:offchain_id); + + // add liquidity + revolut_ramp.add_liquidity(:amount, :offchain_id); + + // withdrawer initiates withdrawal + start_cheat_caller_address(revolut_ramp.contract_address, withdrawer); + revolut_ramp.register(offchain_id: withdrawer_offchain_id); + revolut_ramp.initiate_liquidity_withdrawal(:liquidity_key, :amount, offchain_id: withdrawer_offchain_id); + + // withdrawer withdraws + revolut_ramp.withdraw_liquidity(:liquidity_key, offchain_id: withdrawer_offchain_id, proof: Proof { foo: 0 }); + + // withdrawer withdraws again + revolut_ramp.withdraw_liquidity(:liquidity_key, offchain_id: withdrawer_offchain_id, proof: Proof { foo: 0 }); } //