Skip to content

Commit d69d570

Browse files
author
Rahul Maganti
committed
rate_limit: add fuzz test for backflow
1 parent c83eb3a commit d69d570

File tree

1 file changed

+148
-2
lines changed

1 file changed

+148
-2
lines changed

evm/test/RateLimit.t.sol

+148-2
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,7 @@ contract TestRateLimit is Test, IRateLimiterEvents {
598598

599599
TrimmedAmount memory transferAmount = TrimmedAmount(10, 8);
600600
token.approve(address(nttManager), type(uint256).max);
601+
// transfer 10 tokens from user_A -> user_B via the nttManager
601602
nttManager.transfer(
602603
transferAmount.untrim(decimals), chainId, toWormholeFormat(user_B), false, new bytes(1)
603604
);
@@ -609,7 +610,8 @@ contract TestRateLimit is Test, IRateLimiterEvents {
609610
assertEq(token.balanceOf(user_A), mintAmount.sub(transferAmount).untrim(decimals));
610611

611612
{
612-
// assert outbound rate limit decreased
613+
// consumed capacity on the outbound side
614+
// assert outbound capacity decreased
613615
IRateLimiter.RateLimitParams memory outboundLimitParams =
614616
nttManager.getOutboundLimitParams();
615617
assertEq(
@@ -639,7 +641,151 @@ contract TestRateLimit is Test, IRateLimiterEvents {
639641
assertEq(token.balanceOf(user_A), mintAmount.untrim(decimals));
640642

641643
{
642-
// assert that the inbound limits decreased
644+
// consume capacity on the inbound side
645+
// assert that the inbound capacity decreased
646+
IRateLimiter.RateLimitParams memory inboundLimitParams =
647+
nttManager.getInboundLimitParams(TransceiverHelpersLib.SENDING_CHAIN_ID);
648+
assertEq(
649+
inboundLimitParams.currentCapacity.getAmount(),
650+
inboundLimitParams.limit.sub(transferAmount).getAmount()
651+
);
652+
assertEq(inboundLimitParams.lastTxTimestamp, receiveTime);
653+
}
654+
655+
{
656+
// assert that outbound limit is at max again (because of backflow)
657+
IRateLimiter.RateLimitParams memory outboundLimitParams =
658+
nttManager.getOutboundLimitParams();
659+
assertEq(
660+
outboundLimitParams.currentCapacity.getAmount(),
661+
outboundLimitParams.limit.getAmount()
662+
);
663+
assertEq(outboundLimitParams.lastTxTimestamp, receiveTime);
664+
}
665+
666+
// go 1 second into the future
667+
uint256 sendAgainTime = receiveTime + 1;
668+
vm.warp(sendAgainTime);
669+
670+
// transfer 10 back to the contract
671+
vm.startPrank(user_A);
672+
673+
nttManager.transfer(
674+
transferAmount.untrim(decimals),
675+
TransceiverHelpersLib.SENDING_CHAIN_ID,
676+
toWormholeFormat(user_B),
677+
false,
678+
new bytes(1)
679+
);
680+
681+
vm.stopPrank();
682+
683+
{
684+
// assert outbound rate limit decreased
685+
IRateLimiter.RateLimitParams memory outboundLimitParams =
686+
nttManager.getOutboundLimitParams();
687+
assertEq(
688+
outboundLimitParams.currentCapacity.getAmount(),
689+
outboundLimitParams.limit.sub(transferAmount).getAmount()
690+
);
691+
assertEq(outboundLimitParams.lastTxTimestamp, sendAgainTime);
692+
}
693+
694+
{
695+
// assert that the inbound limit is at max again (because of backflow)
696+
IRateLimiter.RateLimitParams memory inboundLimitParams =
697+
nttManager.getInboundLimitParams(TransceiverHelpersLib.SENDING_CHAIN_ID);
698+
assertEq(
699+
inboundLimitParams.currentCapacity.getAmount(), inboundLimitParams.limit.getAmount()
700+
);
701+
assertEq(inboundLimitParams.lastTxTimestamp, sendAgainTime);
702+
}
703+
}
704+
705+
// helper functions
706+
function setupToken() public returns (address, address, DummyToken, uint8) {
707+
address user_A = address(0x123);
708+
address user_B = address(0x456);
709+
710+
DummyToken token = DummyToken(nttManager.token());
711+
712+
uint8 decimals = token.decimals();
713+
assertEq(decimals, 18);
714+
715+
return (user_A, user_B, token, decimals);
716+
}
717+
718+
function initializeTransceivers() public returns (ITransceiverReceiver[] memory) {
719+
(DummyTransceiver e1, DummyTransceiver e2) =
720+
TransceiverHelpersLib.setup_transceivers(nttManager);
721+
722+
ITransceiverReceiver[] memory transceivers = new ITransceiverReceiver[](2);
723+
transceivers[0] = e1;
724+
transceivers[1] = e2;
725+
726+
return transceivers;
727+
}
728+
729+
// transfer tokens from user_A to user_B
730+
// this consumes capacity on the outbound side
731+
// send tokens from user_B to user_A
732+
// this consumes capacity on the inbound side
733+
// send tokens from user_A to user_B
734+
// this should consume capacity on the outbound side
735+
// and backfill the inbound side
736+
function testFuzz_CircularFlowBackFilling(uint64 mintAmt, uint64 transferAmt) public {
737+
vm.assume(transferAmt > 0 && transferAmt < mintAmt);
738+
739+
(address user_A, address user_B, DummyToken token, uint8 decimals) = setupToken();
740+
741+
TrimmedAmount memory mintAmount = TrimmedAmount(mintAmt, 8);
742+
token.mintDummy(address(user_A), mintAmount.untrim(decimals));
743+
nttManager.setOutboundLimit(mintAmount.untrim(decimals));
744+
745+
// transfer 10 tokens
746+
vm.startPrank(user_A);
747+
748+
TrimmedAmount memory transferAmount = TrimmedAmount(transferAmt, 8);
749+
token.approve(address(nttManager), type(uint256).max);
750+
// transfer tokens from user_A -> user_B via the nttManager
751+
nttManager.transfer(
752+
transferAmount.untrim(decimals), chainId, toWormholeFormat(user_B), false, new bytes(1)
753+
);
754+
755+
vm.stopPrank();
756+
757+
// assert nttManager has 10 tokens and user_A has 10 fewer tokens
758+
assertEq(token.balanceOf(address(nttManager)), transferAmount.untrim(decimals));
759+
assertEq(token.balanceOf(user_A), mintAmount.sub(transferAmount).untrim(decimals));
760+
761+
{
762+
// consumed capacity on the outbound side
763+
// assert outbound capacity decreased
764+
IRateLimiter.RateLimitParams memory outboundLimitParams =
765+
nttManager.getOutboundLimitParams();
766+
assertEq(
767+
outboundLimitParams.currentCapacity.getAmount(),
768+
outboundLimitParams.limit.sub(transferAmount).getAmount()
769+
);
770+
assertEq(outboundLimitParams.lastTxTimestamp, initialBlockTimestamp);
771+
}
772+
773+
// go 1 second into the future
774+
uint256 receiveTime = initialBlockTimestamp + 1;
775+
vm.warp(receiveTime);
776+
777+
ITransceiverReceiver[] memory transceivers = initializeTransceivers();
778+
// now receive tokens from user_B -> user_A
779+
TransceiverHelpersLib.attestTransceiversHelper(
780+
user_A, 0, chainId, nttManager, nttManager, transferAmount, mintAmount, transceivers
781+
);
782+
783+
// assert that user_A has original amount
784+
assertEq(token.balanceOf(user_A), mintAmount.untrim(decimals));
785+
786+
{
787+
// consume capacity on the inbound side
788+
// assert that the inbound capacity decreased
643789
IRateLimiter.RateLimitParams memory inboundLimitParams =
644790
nttManager.getInboundLimitParams(TransceiverHelpersLib.SENDING_CHAIN_ID);
645791
assertEq(

0 commit comments

Comments
 (0)