Skip to content

Commit

Permalink
[ETHEREUM-CONTRACTS] BatchLiquidator: don't revert for non-transferra…
Browse files Browse the repository at this point in the history
…ble SuperTokens (#1707)

* don't revert for non-transferrable SuperTokens

* add test for custom tokens revert on transfer

---------

Co-authored-by: Axe <[email protected]>
  • Loading branch information
d10r and ngmachado authored Oct 16, 2023
1 parent eab7af4 commit 9bba415
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ contract BatchLiquidator {
{
uint256 balance = ERC20(superToken).balanceOf(address(this));
if (balance > 0) {
ERC20(superToken).transferFrom(address(this), msg.sender, balance);
// don't fail for non-transferrable tokens
try ERC20(superToken).transferFrom(address(this), msg.sender, balance)
// solhint-disable-next-line no-empty-blocks
{} catch {}
}
}
}
Expand Down Expand Up @@ -110,7 +113,9 @@ contract BatchLiquidator {
{
uint256 balance = ERC20(superToken).balanceOf(address(this));
if (balance > 0) {
ERC20(superToken).transferFrom(address(this), msg.sender, balance);
try ERC20(superToken).transferFrom(address(this), msg.sender, balance)
// solhint-disable-next-line no-empty-blocks
{} catch {}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,30 @@
pragma solidity 0.8.19;

import { FoundrySuperfluidTester, SuperTokenV1Library } from "../FoundrySuperfluidTester.sol";
import { ISuperToken } from "../../../contracts/superfluid/SuperToken.sol";
import { ISuperToken, SuperToken, ISuperfluid, IConstantOutflowNFT, IConstantInflowNFT } from "../../../contracts/superfluid/SuperToken.sol";
import { BatchLiquidator } from "../../../contracts/utils/BatchLiquidator.sol";
import "forge-std/Test.sol";

contract NonTransferableST is SuperToken {
// transferFrom will always revert
constructor(
ISuperfluid host
)
SuperToken(host, IConstantOutflowNFT(address(0)), IConstantInflowNFT(address(0))) // solhint-disable-next-line no-empty-blocks
{
}

function transferFrom(address holder, address recipient, uint256 amount) public override returns (bool) {
revert();
}

function mintInternal(
address to,
uint256 amount
) external {
_mint(msg.sender, to, amount, false /* invokeHook */, false /* requireReceptionAck */, "", "");
}
}

contract BatchLiquidatorTest is FoundrySuperfluidTester {
using SuperTokenV1Library for ISuperToken;
Expand All @@ -13,11 +35,14 @@ contract BatchLiquidatorTest is FoundrySuperfluidTester {

int96 internal constant FLOW_RATE = 10000000000;

ISuperToken badToken;

constructor() FoundrySuperfluidTester(5) { }

function setUp() public override {
super.setUp();
batchLiquidator = new BatchLiquidator(address(sf.host), address(sf.cfa));
badToken = new NonTransferableST(sf.host);
}

// Helpers
Expand Down Expand Up @@ -129,4 +154,54 @@ contract BatchLiquidatorTest is FoundrySuperfluidTester {
);
vm.stopPrank();
}

function testLiquidationWithCustomTokenRevert() public {
NonTransferableST(address(badToken)).mintInternal(alice, 10 ether);

vm.startPrank(alice);
badToken.createFlow(bob, FLOW_RATE);
badToken.transferAll(admin);
vm.warp(4 hours); // jump 4 hours
vm.stopPrank();
vm.startPrank(liquidator);

batchLiquidator.deleteFlow(address(badToken), alice, bob);
_assertNoFlow(alice, bob);

assertTrue(
superToken.balanceOf(liquidator) == 0, "BatchLiquidator: SL - Balance should be 0 because of revert"
);
vm.stopPrank();

}

function testBatchLiquidationWithCustomTokenRevert() public {
NonTransferableST(address(badToken)).mintInternal(alice, 10 ether);
NonTransferableST(address(badToken)).mintInternal(bob, 10 ether);

vm.startPrank(alice);
badToken.createFlow(bob, FLOW_RATE);
badToken.transferAll(admin);
vm.stopPrank();

vm.startPrank(bob);
badToken.createFlow(carol, FLOW_RATE);
badToken.transferAll(admin);
vm.stopPrank();

vm.warp(4 hours); // jump 4 hours

vm.startPrank(liquidator);

address[] memory senders = new address[](2);
address[] memory receivers = new address[](2);
senders[0] = alice;
senders[1] = bob;
receivers[0] = bob;
receivers[1] = carol;

batchLiquidator.deleteFlows(address(superToken), senders, receivers);
_assertNoFlow(alice, bob);
_assertNoFlow(bob, carol);
}
}

0 comments on commit 9bba415

Please sign in to comment.