Skip to content

Commit

Permalink
Test custodian (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xgregthedev authored Oct 7, 2023
1 parent 6e4afa7 commit b1711c8
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 84 deletions.
70 changes: 37 additions & 33 deletions .gas-snapshot
Original file line number Diff line number Diff line change
@@ -1,36 +1,40 @@
EnforcerTest:testCollateralEnforcer() (gas: 959475)
EnforcerTest:testFailCollateralEnforcerDifferentCollateral() (gas: 842116)
EnforcerTest:testFailRateEnforcerMaxCarryRate() (gas: 797272)
EnforcerTest:testFailRateEnforcerMaxRate() (gas: 797222)
EnforcerTest:testFailRateEnforcerMaxRateAndMaxCarryRate() (gas: 797087)
EnforcerTest:testRateEnforcerBasic() (gas: 916734)
EnforcerTest:testTermEnforcerBasic() (gas: 988996)
TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecall() (gas: 978416)
TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLender() (gas: 889991)
TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLiquidation() (gas: 923967)
TestCustodian:testCustodySelector() (gas: 7084)
TestCustodian:testGenerateOrder() (gas: 165936)
TestCustodian:testGetBorrower() (gas: 70626)
TestCustodian:testOnlySeaport() (gas: 17842)
TestCustodian:testPreviewOrder() (gas: 207)
TestCustodian:testRatifyOrder() (gas: 164)
TestCustodian:testSafeTransferReceive() (gas: 158751)
TestCustodian:testSeaportMetadata() (gas: 8518)
TestCustodian:testSupportsInterface() (gas: 5664)
TestExoticLoans:testSwap() (gas: 1356417)
EnforcerTest:testCollateralEnforcer() (gas: 973177)
EnforcerTest:testFailCollateralEnforcerDifferentCollateral() (gas: 855101)
EnforcerTest:testFailRateEnforcerMaxCarryRate() (gas: 810244)
EnforcerTest:testFailRateEnforcerMaxRate() (gas: 810194)
EnforcerTest:testFailRateEnforcerMaxRateAndMaxCarryRate() (gas: 810059)
EnforcerTest:testRateEnforcerBasic() (gas: 930425)
EnforcerTest:testTermEnforcerBasic() (gas: 1002689)
TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecall() (gas: 988282)
TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLender() (gas: 906210)
TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLiquidation() (gas: 952988)
TestCustodian:testCustodySelector() (gas: 7152)
TestCustodian:testGenerateOrderRepay() (gas: 174157)
TestCustodian:testGenerateOrderRepayNotBorrower() (gas: 102146)
TestCustodian:testGenerateOrderSettlement() (gas: 125008)
TestCustodian:testGenerateOrderSettlementUnauthorized() (gas: 100145)
TestCustodian:testGetBorrower() (gas: 75840)
TestCustodian:testOnlySeaport() (gas: 17931)
TestCustodian:testPreviewOrderNoActiveLoan() (gas: 229)
TestCustodian:testPreviewOrderRepay() (gas: 224706)
TestCustodian:testPreviewOrderSettlement() (gas: 152470)
TestCustodian:testRatifyOrder() (gas: 188716)
TestCustodian:testSafeTransferReceive() (gas: 159061)
TestCustodian:testSeaportMetadata() (gas: 8519)
TestCustodian:testSupportsInterface() (gas: 5791)
TestExoticLoans:testSwap() (gas: 1167541)
TestLoanCombinations:testLoan20For721SimpleInterestDutchFixedRepay() (gas: 252)
TestLoanCombinations:testLoan20for20SimpleInterestDutchFixedRepay() (gas: 512554)
TestLoanCombinations:testLoan721for20SimpleInterestDutchFixedRepay() (gas: 736003)
TestLoanCombinations:testLoanAstariaSettlementRepay() (gas: 510525)
TestLoanCombinations:testLoanSimpleInterestEnglishFixed() (gas: 721961)
TestLoanManager:testGenerateOrder() (gas: 773998)
TestLoanManager:testGenerateOrderInvalidSender() (gas: 13012)
TestLoanManager:testSupportsInterface() (gas: 6959)
TestNewLoan:testBuyNowPayLater() (gas: 1142014)
TestNewLoan:testNewLoanERC721CollateralDefaultTerms2():((uint256,address,address,address,address,(uint8,address,uint256,uint256)[],(uint8,address,uint256,uint256)[],(address,bytes,address,bytes,address,bytes))) (gas: 987827)
TestNewLoan:testNewLoanERC721CollateralDefaultTermsRefinance() (gas: 648642)
TestNewLoan:testNewLoanERC721CollateralDefaultTermsWithMerkleProof():((uint256,address,address,address,address,(uint8,address,uint256,uint256)[],(uint8,address,uint256,uint256)[],(address,bytes,address,bytes,address,bytes))) (gas: 581561)
TestNewLoan:testSettleLoan() (gas: 1260082)
TestRepayLoan:testRepayLoan() (gas: 719171)
TestLoanCombinations:testLoan20for20SimpleInterestDutchFixedRepay() (gas: 521951)
TestLoanCombinations:testLoan721for20SimpleInterestDutchFixedRepay() (gas: 753642)
TestLoanCombinations:testLoanAstariaSettlementRepay() (gas: 519386)
TestLoanCombinations:testLoanSimpleInterestEnglishFixed() (gas: 740159)
TestLoanManager:testGenerateOrder() (gas: 1009691)
TestLoanManager:testGenerateOrderInvalidSender() (gas: 13075)
TestLoanManager:testSupportsInterface() (gas: 7003)
TestNewLoan:testBuyNowPayLater() (gas: 1154993)
TestNewLoan:testNewLoanERC721CollateralDefaultTerms2():((uint256,address,address,address,address,(uint8,address,uint256,uint256)[],(uint8,address,uint256,uint256)[],(address,bytes,address,bytes,address,bytes))) (gas: 1001549)
TestNewLoan:testNewLoanERC721CollateralDefaultTermsRefinance() (gas: 658024)
TestNewLoan:testSettleLoan() (gas: 1282926)
TestRepayLoan:testRepayLoan() (gas: 736801)
TestStarLiteUtils:testEncodeReceivedWithRecipient() (gas: 17955)
TestStarLiteUtils:testSpentToReceived() (gas: 17796)
1 change: 0 additions & 1 deletion src/ConduitHelper.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
pragma solidity =0.8.17;


import {ItemType, OfferItem, Schema, SpentItem, ReceivedItem} from "seaport-types/src/lib/ConsiderationStructs.sol";

import {ConduitTransfer, ConduitItemType} from "seaport-types/src/conduit/lib/ConduitStructs.sol";
Expand Down
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
21 changes: 12 additions & 9 deletions src/originators/Originator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,17 @@ abstract contract Originator is Ownable {
INITIALIZED,
CLOSED
}

error InvalidDebt();
error InvalidOffer();

struct Response {
LoanManager.Terms terms;
address issuer;
}

event StrategistTransferred(address newStrategist);

mapping(bytes32 => bool) public usedHashes;

struct Request {
Expand All @@ -56,7 +60,7 @@ abstract contract Originator is Ownable {
}

struct Details {
// uint16 offerType;
// uint16 offerType;
address custodian;
address conduit;
address issuer;
Expand Down Expand Up @@ -170,19 +174,18 @@ abstract contract Originator is Ownable {
return abi.decode(details, (Details)).offer.terms;
}

function execute(Request calldata params)
external
virtual
onlyLoanManager
returns (Response memory response)
{
function execute(Request calldata params) external virtual onlyLoanManager returns (Response memory response) {
Details memory details = abi.decode(params.details, (Details));
_validateOffer(params, details);
_execute(params, details);
response = _buildResponse(params, details);
}

function _buildResponse(Request calldata params, Details memory details) internal virtual returns (Response memory response) {
function _buildResponse(Request calldata params, Details memory details)
internal
virtual
returns (Response memory response)
{
response = Response({terms: details.offer.terms, issuer: details.issuer});
}

Expand Down Expand Up @@ -242,7 +245,7 @@ abstract contract Originator is Ownable {

if (
ConduitInterface(details.conduit).execute(_packageTransfers(request.debt, request.receiver, details.issuer))
!= ConduitInterface.execute.selector
!= ConduitInterface.execute.selector
) {
revert ConduitTransferError();
}
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 {}
}
24 changes: 12 additions & 12 deletions test/TestExoticLoans.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ contract SwapHandler is SettlementHandler {
}

function getSettlement(LoanManager.Loan calldata loan)
public
view
override
returns (ReceivedItem[] memory consideration, address restricted)
public
view
override
returns (ReceivedItem[] memory consideration, address restricted)
{
return (new ReceivedItem[](0), address(0));
}
Expand All @@ -76,19 +76,19 @@ contract SwapPricing is Pricing {
constructor(LoanManager LM_) Pricing(LM_) {}

function getPaymentConsideration(LoanManager.Loan memory loan)
public
view
override
returns (ReceivedItem[] memory, ReceivedItem[] memory)
public
view
override
returns (ReceivedItem[] memory, ReceivedItem[] memory)
{
return (new ReceivedItem[](0), new ReceivedItem[](0));
}

function isValidRefinance(LoanManager.Loan memory loan, bytes memory newPricingData, address caller)
external
view
override
returns (ReceivedItem[] memory, ReceivedItem[] memory, ReceivedItem[] memory)
external
view
override
returns (ReceivedItem[] memory, ReceivedItem[] memory, ReceivedItem[] memory)
{
return (new ReceivedItem[](0), new ReceivedItem[](0), new ReceivedItem[](0));
}
Expand Down
Loading

0 comments on commit b1711c8

Please sign in to comment.