Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/AstariaXYZ/starport into HEAD
Browse files Browse the repository at this point in the history
  • Loading branch information
SantiagoGregory committed Sep 15, 2023
2 parents 1a6b45f + 83b8961 commit 7d34699
Show file tree
Hide file tree
Showing 11 changed files with 280 additions and 49 deletions.
11 changes: 9 additions & 2 deletions .gas-snapshot
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
TestStarLite:testNewLoan() (gas: 2424939)
TestStarLite:testRepayLoan() (gas: 3078108)
TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecall() (gas: 952394)
TestLoanManager:testStorage() (gas: 2283158165)
TestLoanManager:testSupportsInterface() (gas: 6937)
TestNewLoan:testBuyNowPayLater() (gas: 1141902)
TestNewLoan:testNewLoanERC721CollateralDefaultTerms2():((uint256,address,address,address,address,(uint8,address,uint256,uint256)[],(uint8,address,uint256,uint256)[],(address,bytes,address,bytes,address,bytes))) (gas: 987750)
TestNewLoan:testNewLoanERC721CollateralDefaultTermsRefinance() (gas: 648498)
TestNewLoan:testNewLoanERC721CollateralDefaultTermsWithMerkleProof():((uint256,address,address,address,address,(uint8,address,uint256,uint256)[],(uint8,address,uint256,uint256)[],(address,bytes,address,bytes,address,bytes))) (gas: 581604)
TestNewLoan:testSettleLoan() (gas: 1260468)
TestRepayLoan:testRepayLoan() (gas: 718985)
TestStarLiteUtils:testEncodeReceivedWithRecipient() (gas: 17955)
TestStarLiteUtils:testSpentToReceived() (gas: 17796)
29 changes: 17 additions & 12 deletions src/LoanManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -469,20 +469,21 @@ contract LoanManager is ERC721, ContractOffererInterface, ConduitHelper {
bytes32 caveatHash
) internal returns (SpentItem[] memory offer) {
offer = new SpentItem[](debt.length + 1);
offer[0] = SpentItem({
itemType: ItemType.ERC721,
token: address(this),
identifier: uint256(caveatHash),
amount: 1
});
uint256 i = 0;
for (; i < debt.length; ) {
offer[i + 1] = debt[i];

for (uint256 i; i < debt.length; ) {
offer[i] = debt[i];
_setDebtApprovals(debt[i]);
unchecked {
++i;
}
}

offer[debt.length] = SpentItem({
itemType: ItemType.ERC721,
token: address(this),
identifier: uint256(caveatHash),
amount: 1
});
}

function transferFrom(
Expand Down Expand Up @@ -546,6 +547,7 @@ contract LoanManager is ERC721, ContractOffererInterface, ConduitHelper {
address conduit
) external {
(, , address conduitController) = seaport.information();

if (
ConduitControllerInterface(conduitController).ownerOf(conduit) !=
msg.sender
Expand Down Expand Up @@ -575,16 +577,19 @@ contract LoanManager is ERC721, ContractOffererInterface, ConduitHelper {
refinanceConsideration = _removeZeroAmounts(refinanceConsideration);

// if for malicious or non-malicious the refinanceConsideration is zero
if (refinanceConsideration.length == 0)
if (refinanceConsideration.length == 0) {
revert InvalidNoRefinanceConsideration();
}

_settle(loan);
uint256 i = 0;
for (; i < loan.debt.length; ) {

for (uint256 i; i < loan.debt.length; ) {
loan.debt[i].amount = considerationPayment[i].amount;
unchecked {
++i;
}
}

if (
ConduitInterface(conduit).execute(
_packageTransfers(refinanceConsideration, msg.sender)
Expand Down
28 changes: 15 additions & 13 deletions src/hooks/BaseRecall.sol
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@ abstract contract BaseRecall is ConduitHelper {
bytes memory encodedLoan = abi.encode(loan);

uint256 loanId = uint256(keccak256(encodedLoan));

if (!LM.active(loanId)) revert LoanDoesNotExist();

recalls[loanId] = Recall(payable(msg.sender), uint64(block.timestamp));
emit Recalled(loanId, msg.sender, loan.start + details.recallWindow);
}
Expand All @@ -131,8 +133,10 @@ abstract contract BaseRecall is ConduitHelper {

Recall storage recall = recalls[loanId];
// ensure that a recall exists for the provided tokenId, ensure that the recall
if (recall.start == 0 || recall.recaller == address(0))
if (recall.start == 0 || recall.recaller == address(0)) {
revert WithdrawDoesNotExist();
}

ReceivedItem[] memory recallConsideration = _generateRecallConsideration(
loan,
0,
Expand All @@ -143,13 +147,15 @@ abstract contract BaseRecall is ConduitHelper {
recall.recaller = payable(address(0));
recall.start = 0;

uint256 i = 0;
for (; i < recallConsideration.length; ) {
for (uint256 i; i < recallConsideration.length; ) {

if (loan.debt[i].itemType != ItemType.ERC20) revert InvalidStakeType();

ERC20(loan.debt[i].token).transfer(
receiver,
recallConsideration[i].amount
);

unchecked {
++i;
}
Expand All @@ -168,17 +174,15 @@ abstract contract BaseRecall is ConduitHelper {
(BasePricing.Details)
);
recallStake = new uint256[](loan.debt.length);
uint256 i = 0;
for (; i < loan.debt.length; ) {
uint256 delta_t = end - start;
uint256 stake = BasePricing(loan.terms.pricing).getInterest(
for (uint256 i; i < loan.debt.length; ) {
recallStake[i] = BasePricing(loan.terms.pricing).getInterest(
loan,
details,
start,
end,
i
);
recallStake[i] = stake;

unchecked {
++i;
}
Expand Down Expand Up @@ -210,14 +214,12 @@ abstract contract BaseRecall is ConduitHelper {
) internal view returns (ReceivedItem[] memory consideration) {
uint256[] memory stake = _getRecallStake(loan, start, end);
consideration = new ReceivedItem[](stake.length);
uint256 i = 0;
for (; i < consideration.length; ) {

for (uint256 i; i < consideration.length; ) {
consideration[i] = ReceivedItem({
itemType: loan.debt[i].itemType,
identifier: loan.debt[i].identifier,
amount: stake.length == consideration.length
? stake[i].mulWad(proportion)
: stake[0].mulWad(proportion),
amount: stake[i].mulWad(proportion),
token: loan.debt[i].token,
recipient: receiver
});
Expand Down
51 changes: 29 additions & 22 deletions test/StarPortTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -498,16 +498,9 @@ contract StarPortTest is BaseOrderTest {
)
);
OfferItem[] memory offer = new OfferItem[](nlr.debt.length + 1);
offer[0] = OfferItem({
itemType: ItemType.ERC721,
token: address(LM),
identifierOrCriteria: uint256(caveatHash),
startAmount: 1,
endAmount: 1
});
uint256 i = 0;
for (; i < debt.length; ) {
offer[i + 1] = OfferItem({

for (uint256 i; i < debt.length; ) {
offer[i] = OfferItem({
itemType: debt[i].itemType,
token: debt[i].token,
identifierOrCriteria: debt[i].identifier,
Expand All @@ -519,6 +512,14 @@ contract StarPortTest is BaseOrderTest {
}
}

offer[nlr.debt.length] = OfferItem({
itemType: ItemType.ERC721,
token: address(LM),
identifierOrCriteria: uint256(caveatHash),
startAmount: 1,
endAmount: 1
});

OfferItem[] memory zOffer = new OfferItem[](1);
zOffer[0] = OfferItem({
itemType: nlr.debt[0].itemType,
Expand Down Expand Up @@ -578,7 +579,7 @@ contract StarPortTest is BaseOrderTest {

fill[0].offerComponents[0] = FulfillmentComponent({
orderIndex: 1,
itemIndex: 1
itemIndex: 0
});
fill[0].considerationComponents[0] = FulfillmentComponent({
orderIndex: 0,
Expand All @@ -593,6 +594,7 @@ contract StarPortTest is BaseOrderTest {
orderIndex: 2,
itemIndex: 0
});

fill[1].considerationComponents[0] = FulfillmentComponent({
orderIndex: 0,
itemIndex: 0
Expand All @@ -607,19 +609,22 @@ contract StarPortTest is BaseOrderTest {
orderIndex: 0,
itemIndex: 0
});

fill[2].considerationComponents[0] = FulfillmentComponent({
orderIndex: 1,
itemIndex: 0
});

fill[3] = Fulfillment({
offerComponents: new FulfillmentComponent[](1),
considerationComponents: new FulfillmentComponent[](1)
});

fill[3].offerComponents[0] = FulfillmentComponent({
orderIndex: 1,
itemIndex: 0
itemIndex: 1
});

fill[3].considerationComponents[0] = FulfillmentComponent({
orderIndex: 2,
itemIndex: 0
Expand Down Expand Up @@ -661,16 +666,9 @@ contract StarPortTest is BaseOrderTest {
)
);
OfferItem[] memory offer = new OfferItem[](nlr.debt.length + 1);
offer[0] = OfferItem({
itemType: ItemType.ERC721,
token: address(LM),
identifierOrCriteria: uint256(caveatHash),
startAmount: 1,
endAmount: 1
});
uint256 i = 0;
for (; i < debt.length; ) {
offer[i + 1] = OfferItem({

for (uint i; i < debt.length; ) {
offer[i] = OfferItem({
itemType: debt[i].itemType,
token: debt[i].token,
identifierOrCriteria: debt[i].identifier,
Expand All @@ -681,6 +679,15 @@ contract StarPortTest is BaseOrderTest {
++i;
}
}

offer[nlr.debt.length] = OfferItem({
itemType: ItemType.ERC721,
token: address(LM),
identifierOrCriteria: uint256(caveatHash),
startAmount: 1,
endAmount: 1
});

OrderParameters memory op = _buildContractOrder(
address(LM),
nlr.caveats.length == 0 ? new OfferItem[](0) : offer,
Expand Down
25 changes: 25 additions & 0 deletions test/utils/Assertions.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

//Assert balances are correct after new loan is created
modifier newLoanAssertions() {

uint256 borrowerBalance;

_;

//Assert updated balances are correct

}


//Assert balances are correct after loan is repaid
modifier repayAssertions() {

uint256 borrowerBalance;

_;

//Assert updated balances are correct

}


64 changes: 64 additions & 0 deletions test/utils/Bound.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
pragma solidity =0.8.17;

import {
ItemType,
SpentItem,
ReceivedItem
} from "seaport-types/src/lib/ConsiderationStructs.sol";
import {Cast} from "test/utils/Cast.sol";
import "test/utils/FuzzStructs.sol" as Fuzz;
import "forge-std/Test.sol";

abstract contract Bound is StdUtils {
using Cast for *;

function _boundItemType(uint8 itemType) internal pure returns (ItemType) {
return
_bound(
itemType,
uint8(ItemType.NATIVE),
uint8(ItemType.ERC1155_WITH_CRITERIA)
).toItemType();
}

function _boundSpentItem(
Fuzz.SpentItem memory input
) internal pure returns (SpentItem memory ret) {
ret = SpentItem({
itemType: _boundItemType(input.itemType),
token: input.token,
identifier: input.identifier,
amount: input.amount
});
}

function _boundSpentItems(
Fuzz.SpentItem[] memory input
) internal pure returns (SpentItem[] memory ret) {
ret = new SpentItem[](input.length);
for (uint256 i = 0; i < input.length; i++) {
ret[i] = _boundSpentItem(input[i]);
}
}

function _boundReceivedItem(
Fuzz.ReceivedItem memory input
) internal pure returns (ReceivedItem memory ret) {
ret = ReceivedItem({
itemType: _boundItemType(input.itemType),
token: input.token,
identifier: input.identifier,
amount: input.amount,
recipient: input.recipient
});
}

function _boundReceivedItems(
Fuzz.ReceivedItem[] memory input
) internal pure returns (ReceivedItem[] memory ret) {
ret = new ReceivedItem[](input.length);
for (uint256 i = 0; i < input.length; i++) {
ret[i] = _boundReceivedItem(input[i]);
}
}
}
29 changes: 29 additions & 0 deletions test/utils/Cast.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
pragma solidity =0.8.17;

import {
ItemType,
SpentItem,
ReceivedItem
} from "seaport-types/src/lib/ConsiderationStructs.sol";
import "test/utils/FuzzStructs.sol" as Fuzz;
import "forge-std/Test.sol";

library Cast {
function toUint(uint8 input) internal pure returns (uint256 ret) {
assembly {
ret := input
}
}

function toUint(address input) internal pure returns (uint256 ret) {
assembly {
ret := input
}
}

function toItemType(uint256 input) internal pure returns (ItemType ret) {
assembly {
ret := input
}
}
}
Loading

0 comments on commit 7d34699

Please sign in to comment.