Skip to content

Commit

Permalink
Additional custodian testing and MockCall utils
Browse files Browse the repository at this point in the history
  • Loading branch information
0xgregthedev committed Oct 7, 2023
1 parent 6e4afa7 commit 386cd43
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 16 deletions.
18 changes: 10 additions & 8 deletions src/Custodian.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ contract Custodian is ContractOffererInterface, TokenReceiverInterface, ConduitH
event RepayApproval(address borrower, address repayer, bool approved);
event SeaportCompatibleContractDeployed();

error InvalidSender();
error NotSeaport();
error InvalidRepayer();
error InvalidFulfiller();
error InvalidHandler();

constructor(LoanManager LM_, address seaport_) {
Expand Down Expand Up @@ -86,7 +88,7 @@ contract Custodian is ContractOffererInterface, TokenReceiverInterface, ConduitH

modifier onlySeaport() {
if (msg.sender != address(seaport)) {
revert InvalidSender();
revert NotSeaport();
}
_;
}
Expand Down Expand Up @@ -253,7 +255,7 @@ contract Custodian is ContractOffererInterface, TokenReceiverInterface, ConduitH
if (SettlementHook(loan.terms.hook).isActive(loan)) {
address borrower = getBorrower(loan);
if (fulfiller != borrower && !repayApproval[borrower][fulfiller]) {
revert InvalidSender();
revert InvalidRepayer();
}

(ReceivedItem[] memory paymentConsiderations, ReceivedItem[] memory carryFeeConsideration) =
Expand All @@ -267,19 +269,19 @@ contract Custodian is ContractOffererInterface, TokenReceiverInterface, ConduitH
_settleLoan(loan);
}
} else {
address restricted;
address authorized;
//add in originator fee
if (withEffects) {
_beforeSettlementHandlerHook(loan);
(consideration, restricted) = SettlementHandler(loan.terms.handler).getSettlement(loan);
(consideration, authorized) = SettlementHandler(loan.terms.handler).getSettlement(loan);
_afterSettlementHandlerHook(loan);
} else {
(consideration, restricted) = SettlementHandler(loan.terms.handler).getSettlement(loan);
(consideration, authorized) = SettlementHandler(loan.terms.handler).getSettlement(loan);
}

//TODO: remove and revert in get settlement if needed
if (restricted != address(0) && fulfiller != restricted) {
revert InvalidSender();
if (authorized != address(0) && fulfiller != authorized) {
revert InvalidFulfiller();
}
}

Expand Down
100 changes: 92 additions & 8 deletions test/TestCustodian.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import "./StarPortTest.sol";
import {DeepEq} from "test/utils/DeepEq.sol";
import {MockCall} from "test/utils/MockCall.sol";
import "forge-std/Test.sol";

contract TestCustodian is StarPortTest {
contract TestCustodian is StarPortTest, DeepEq, MockCall {
using Cast for *;

LoanManager.Loan public activeLoan;
Expand Down Expand Up @@ -49,10 +52,10 @@ contract TestCustodian is StarPortTest {
}

function testOnlySeaport() public {
vm.expectRevert(abi.encodeWithSelector(Custodian.InvalidSender.selector));
vm.expectRevert(abi.encodeWithSelector(Custodian.NotSeaport.selector));
custodian.ratifyOrder(new SpentItem[](0), new ReceivedItem[](0), new bytes(0), new bytes32[](0), uint256(0));

vm.expectRevert(abi.encodeWithSelector(Custodian.InvalidSender.selector));
vm.expectRevert(abi.encodeWithSelector(Custodian.NotSeaport.selector));
custodian.generateOrder(address(this), new SpentItem[](0), new SpentItem[](0), new bytes(0));
}

Expand Down Expand Up @@ -80,8 +83,8 @@ contract TestCustodian is StarPortTest {
custodian.getSeaportMetadata();
}

function testGetBorrower() public view {
custodian.getBorrower(activeLoan.toMemory());
function testGetBorrower() public {
assertEq(custodian.getBorrower(activeLoan.toMemory()), activeLoan.borrower);
}

function testCustodySelector() public {
Expand All @@ -91,12 +94,93 @@ contract TestCustodian is StarPortTest {
);
}

function testGenerateOrder() public {
//TODO: add assertions
function testGenerateOrderRepay() public {
vm.prank(seaportAddr);
custodian.generateOrder(activeLoan.borrower, new SpentItem[](0), debt, abi.encode(activeLoan));
}

function testRatifyOrder() public {}
function testGenerateOrderRepayNotBorrower() public {
vm.prank(seaportAddr);
vm.expectRevert(abi.encodeWithSelector(Custodian.InvalidRepayer.selector));
custodian.generateOrder(alice, new SpentItem[](0), debt, abi.encode(activeLoan));
}

function testGenerateOrderSettlement() public {
vm.startPrank(seaportAddr);
mockHookCall(activeLoan.terms.hook, false);

mockHandlerCall(activeLoan.terms.handler, new ReceivedItem[](0), address(0));

(SpentItem[] memory offer, ReceivedItem[] memory consideration) =
custodian.generateOrder(alice, new SpentItem[](0), debt, abi.encode(activeLoan));

vm.stopPrank();

assertEq(consideration.length, 0);
}

function testGenerateOrderSettlementUnauthorized() public {
vm.prank(seaportAddr);
mockHookCall(activeLoan.terms.hook, false);
mockHandlerCall(activeLoan.terms.handler, new ReceivedItem[](0), lender.addr);

vm.expectRevert(abi.encodeWithSelector(Custodian.InvalidFulfiller.selector));
custodian.generateOrder(borrower.addr, new SpentItem[](0), debt, abi.encode(activeLoan));
}

//TODO: add assertions
function testRatifyOrder() public {
vm.startPrank(seaportAddr);
bytes memory context = abi.encode(activeLoan);

(SpentItem[] memory offer, ReceivedItem[] memory consideration) =
custodian.generateOrder(activeLoan.borrower, new SpentItem[](0), debt, context);

custodian.ratifyOrder(offer, consideration, context, new bytes32[](0), 0);

vm.stopPrank();
}

function testPreviewOrderRepay() public {
vm.prank(seaportAddr);

mockHookCall(activeLoan.terms.hook, true);
mockHandlerCall(activeLoan.terms.handler, new ReceivedItem[](0), address(0));

(SpentItem[] memory expectedOffer, ReceivedItem[] memory expectedConsideration) =
custodian.generateOrder(activeLoan.borrower, new SpentItem[](0), debt, abi.encode(activeLoan));

mockHookCall(activeLoan.terms.hook, true);
mockHandlerCall(activeLoan.terms.handler, new ReceivedItem[](0), address(0));

(SpentItem[] memory receivedOffer, ReceivedItem[] memory receivedCosideration) = custodian.previewOrder(
activeLoan.borrower, activeLoan.borrower, new SpentItem[](0), debt, abi.encode(activeLoan)
);

_deepEq(receivedOffer, expectedOffer);
_deepEq(receivedCosideration, expectedConsideration);
}

function testPreviewOrderSettlement() public {
vm.prank(seaportAddr);

mockHookCall(activeLoan.terms.hook, false);
mockHandlerCall(activeLoan.terms.handler, new ReceivedItem[](0), address(0));

(SpentItem[] memory expectedOffer, ReceivedItem[] memory expectedConsideration) =
custodian.generateOrder(alice, new SpentItem[](0), debt, abi.encode(activeLoan));

mockHookCall(activeLoan.terms.hook, false);
mockHandlerCall(activeLoan.terms.handler, new ReceivedItem[](0), address(0));

(SpentItem[] memory receivedOffer, ReceivedItem[] memory receivedCosideration) =
custodian.previewOrder(alice, alice, new SpentItem[](0), debt, abi.encode(activeLoan));

_deepEq(receivedOffer, expectedOffer);
_deepEq(receivedCosideration, expectedConsideration);
}

function testPreviewOrder() public {}
//TODO: should revert
function testPreviewOrderNoActiveLoan() public {}
}
19 changes: 19 additions & 0 deletions test/utils/MockCall.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {ItemType, SpentItem, ReceivedItem} from "seaport-types/src/lib/ConsiderationStructs.sol";
import {TestBase} from "forge-std/Test.sol";
import {SettlementHook} from "src/hooks/SettlementHook.sol";
import {SettlementHandler} from "src/handlers/SettlementHandler.sol";

abstract contract MockCall is TestBase {

function mockHookCall(address hook, bool status) public {
vm.mockCall(hook, abi.encodeWithSelector(SettlementHook.isActive.selector), abi.encode(status));
}

function mockHandlerCall(address handler, ReceivedItem[] memory receivedItems, address authorized) public {
vm.mockCall(
handler,
abi.encodeWithSelector(SettlementHandler.getSettlement.selector),
abi.encode(receivedItems, authorized)
);
}
}

0 comments on commit 386cd43

Please sign in to comment.