Skip to content

Commit c4f82be

Browse files
authored
Merge pull request #16 from movementlabsxyz/modify-rate-limiter
modify rate limit behavior on incoming funds
2 parents 422ea33 + 1364523 commit c4f82be

3 files changed

Lines changed: 101 additions & 5 deletions

File tree

examples/oft-evm-move-adapters/sources/oft_implementation/move_oft_adapter.move

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ module oft::move_oft_adapter {
2626
assert_not_blocklisted,
2727
debit_view_with_possible_fee,
2828
fee_details_with_possible_fee,
29-
redirect_to_admin_if_blocklisted, release_rate_limit_capacity, try_consume_rate_limit_capacity
29+
redirect_to_admin_if_blocklisted, try_consume_rate_limit_capacity
3030
};
3131
use oft_common::oft_fee_detail::OftFeeDetail;
3232
use oft_common::oft_limit::{Self, OftLimit};
@@ -53,16 +53,16 @@ module oft::move_oft_adapter {
5353
public(friend) fun credit(
5454
to: address,
5555
amount_ld: u64,
56-
src_eid: u32,
56+
_src_eid: u32,
5757
lz_receive_value: Option<FungibleAsset>,
5858
): u64 acquires OftImpl, PauserStore {
5959
// Global inflow pause gate
6060
assert!(!is_paused(), EPAUSED);
6161
// Default implementation does not make special use of LZ Receive Value sent; just deposit to the OFT address
6262
option::for_each(lz_receive_value, |fa| primary_fungible_store::deposit(@oft_admin, fa));
6363

64-
// Release rate limit capacity for the pathway (net inflow)
65-
release_rate_limit_capacity(src_eid, amount_ld);
64+
// Consume rate limit capacity for the pathway (net inflow), based on the amount received on this side
65+
try_consume_rate_limit_capacity(30325, amount_ld);
6666

6767
// unlock the amount from escrow
6868
let escrow_signer = &object::generate_signer_for_extending(&store().escrow_extend_ref);

examples/oft-evm-move-adapters/tests/implementations/move_oft_adapter_tests.move

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,4 +682,99 @@ module oft::move_oft_adapter_tests {
682682
let (min_amount_ld, max_amount_ld) = oft_common::oft_limit::unpack_oft_limit(oft_limit);
683683
assert!(min_amount_ld == 0 && max_amount_ld == 2500, 3);
684684
}
685+
686+
#[test]
687+
#[expected_failure(abort_code = oft::oft_impl_config::EEXCEEDED_RATE_LIMIT)]
688+
fun test_credit_rate_limit_on_endpoint_30325() {
689+
let mint_ref = setup();
690+
691+
// Set up timestamp for rate limiting
692+
timestamp::set_time_has_started_for_testing(&create_signer_for_test(@std));
693+
694+
// Configure rate limit for endpoint 30325 (hardcoded in credit function)
695+
// Limit: 1000 tokens, Window: 100 seconds
696+
let admin = &create_signer_for_test(@oft_admin);
697+
move_oft_adapter::set_rate_limit(admin, 30325, 1000, 100);
698+
699+
let (limit, window) = move_oft_adapter::rate_limit_config(30325);
700+
assert!(limit == 1000 && window == 100, 0);
701+
702+
// First, debit tokens to escrow so we have balance to credit from
703+
let escrow_amount = 2000u64;
704+
let deposit = mint(&mint_ref, escrow_amount);
705+
let (_s, _r) = move_oft_adapter::debit_fungible_asset(@0x999, &mut deposit, 0, 30100);
706+
burn_token_for_test(deposit);
707+
708+
// Verify escrow has funds
709+
let escrow_balance = primary_fungible_store::balance(escrow_address(), move_oft_adapter::metadata());
710+
assert!(escrow_balance == escrow_amount, 1);
711+
712+
let recipient = @0x8888;
713+
create_account_for_test(recipient);
714+
715+
// First credit: 600 tokens (within limit of 1000)
716+
let credited1 = credit(recipient, 600, 30325, option::none());
717+
assert!(credited1 == 600, 2);
718+
719+
// Verify recipient received the tokens
720+
let balance = primary_fungible_store::balance(recipient, move_oft_adapter::metadata());
721+
assert!(balance == 600, 3);
722+
723+
// Second credit: 500 tokens (total would be 1100, exceeding limit of 1000)
724+
// This should fail with EEXCEEDED_RATE_LIMIT
725+
let _credited2 = credit(recipient, 500, 30325, option::none());
726+
}
727+
728+
#[test]
729+
fun test_credit_rate_limit_reset_after_window_30325() {
730+
let mint_ref = setup();
731+
732+
// Set up timestamp for rate limiting
733+
timestamp::set_time_has_started_for_testing(&create_signer_for_test(@std));
734+
735+
// Configure rate limit for endpoint 30325
736+
// Limit: 1000 tokens, Window: 100 seconds
737+
let admin = &create_signer_for_test(@oft_admin);
738+
move_oft_adapter::set_rate_limit(admin, 30325, 1000, 100);
739+
740+
let (limit, window) = move_oft_adapter::rate_limit_config(30325);
741+
assert!(limit == 1000 && window == 100, 0);
742+
743+
// First, debit tokens to escrow so we have balance to credit from
744+
let escrow_amount = 3000u64;
745+
let deposit = mint(&mint_ref, escrow_amount);
746+
let (_s, _r) = move_oft_adapter::debit_fungible_asset(@0x999, &mut deposit, 0, 30100);
747+
burn_token_for_test(deposit);
748+
749+
// Verify escrow has funds
750+
let escrow_balance = primary_fungible_store::balance(escrow_address(), move_oft_adapter::metadata());
751+
assert!(escrow_balance == escrow_amount, 1);
752+
753+
let recipient = @0x8888;
754+
create_account_for_test(recipient);
755+
756+
// First credit: 600 tokens (within limit of 1000)
757+
let credited1 = credit(recipient, 600, 30325, option::none());
758+
assert!(credited1 == 600, 2);
759+
760+
// Verify recipient received the tokens
761+
let balance = primary_fungible_store::balance(recipient, move_oft_adapter::metadata());
762+
assert!(balance == 600, 3);
763+
764+
// Advance time beyond the window (101 seconds in microseconds)
765+
timestamp::fast_forward_seconds(101);
766+
767+
// After the window passes, rate limit should reset
768+
// Credit 800 tokens - should succeed because we're in a new window
769+
let credited2 = credit(recipient, 800, 30325, option::none());
770+
assert!(credited2 == 800, 4);
771+
772+
// Verify recipient received the additional tokens
773+
let balance = primary_fungible_store::balance(recipient, move_oft_adapter::metadata());
774+
assert!(balance == 1400, 5); // 600 + 800
775+
776+
// Verify escrow balance decreased accordingly
777+
let escrow_balance = primary_fungible_store::balance(escrow_address(), move_oft_adapter::metadata());
778+
assert!(escrow_balance == 1600, 6); // 3000 - 600 - 800
779+
}
685780
}

examples/oft-evm-move-adapters/tests/oft_using_move_oft_adapter_tests.move

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ module oft::oft_using_move_oft_adapter_tests {
257257
}
258258

259259
#[test]
260+
#[expected_failure(abort_code = oft::oft_impl_config::EEXCEEDED_RATE_LIMIT)]
260261
fun test_send_rate_limit_netted_by_receive() {
261262
let mint_ref = setup(SRC_EID, DST_EID);
262263
set_rate_limit(&create_signer_for_test(@oft_admin), DST_EID, 19_000_000_000, 10);
@@ -316,7 +317,7 @@ module oft::oft_using_move_oft_adapter_tests {
316317
vector[],
317318
);
318319

319-
// Succeeds: consumes 15_000_000_000 of 19_000_000_000 in flight
320+
// Modified behavior on move_oft_adapter.move, send_withdraw should NOT be offset by lz_receive.
320321
send_withdraw(alice, DST_EID, bob, amount, amount, vector[], vector[], vector[], 0, 0);
321322
}
322323

0 commit comments

Comments
 (0)