Skip to content

Commit

Permalink
working golf
Browse files Browse the repository at this point in the history
  • Loading branch information
0xgregthedev committed Oct 18, 2023
1 parent 4b4ab80 commit aba1c62
Show file tree
Hide file tree
Showing 9 changed files with 258 additions and 130 deletions.
38 changes: 19 additions & 19 deletions src/ConduitHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,29 +35,29 @@ abstract contract ConduitHelper {
//if (repayConsideration.length != carryConsideration.length) {
// revert RepayCarryLengthMismatch();
//}
consideration = new ReceivedItem[](repayConsideration.length +
carryConsideration.length +
additionalConsiderations.length);

uint256 i = 0;
uint256 n = repayConsideration.length;
for (; i < n; i++) {
consideration[i] = repayConsideration[i];
}
uint256 offset = n;
if (carryConsideration.length > 0) {
n += carryConsideration.length;
unchecked {
consideration =
new ReceivedItem[](repayConsideration.length + carryConsideration.length + additionalConsiderations.length);

uint256 i = 0;
uint256 n = repayConsideration.length;
for (; i < n; i++) {
consideration[i] = carryConsideration[i - offset];
consideration[i] = repayConsideration[i];
}
}
if (additionalConsiderations.length > 0) {
offset = n;
n += additionalConsiderations.length;
uint256 offset = n;
if (carryConsideration.length > 0) {
n += carryConsideration.length;
for (; i < n; ++i) {
consideration[i] = carryConsideration[i - offset];
}
}
if (additionalConsiderations.length > 0) {
offset = n;
n += additionalConsiderations.length;

for (; i < n; i++) {
consideration[i] = additionalConsiderations[i - offset];
for (; i < n; ++i) {
consideration[i] = additionalConsiderations[i - offset];
}
}
}
}
Expand Down
57 changes: 3 additions & 54 deletions src/LoanManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -569,20 +569,18 @@ contract LoanManager is ContractOffererInterface, ConduitHelper, Ownable, ERC721
revert InvalidConduit();
}
(
// used to update the new loan amount
// used to update to repay the lender
ReceivedItem[] memory considerationPayment,
// used to pay the carry amount
ReceivedItem[] memory carryPayment,
// note: considerationPayment - carryPayment = amount to pay lender
// considerationPayment + carryPayment = amount = new debt

// used for any additional payments beyond consideration and carry
ReceivedItem[] memory additionalPayment
) = Pricing(loan.terms.pricing).isValidRefinance(loan, newPricingData, msg.sender);

ReceivedItem[] memory refinanceConsideration =
_mergeConsiderations(considerationPayment, carryPayment, additionalPayment);

refinanceConsideration = _removeZeroAmounts(refinanceConsideration);
_removeZeroAmounts(_mergeConsiderations(considerationPayment, carryPayment, additionalPayment));

// if for malicious or non-malicious the refinanceConsideration is zero
if (refinanceConsideration.length == 0) {
Expand Down Expand Up @@ -621,54 +619,5 @@ contract LoanManager is ContractOffererInterface, ConduitHelper, Ownable, ERC721
_issueLoanManager(loan, msg.sender.code.length > 0);
}

function _refinanceRefB(LoanManager.Loan memory loan, bytes memory newPricingData, address conduit) internal {
(,, address conduitController) = seaport.information();

if (ConduitControllerInterface(conduitController).ownerOf(conduit) != msg.sender) {
revert InvalidConduit();
}
(
// used to repay the lender
ReceivedItem[] memory considerationPayment,
// used to pay the carry amount
ReceivedItem[] memory carryPayment,
//carry and consideration both removed from the debt
// used for any additional payments beyond consideration and carry
ReceivedItem[] memory additionalPayment
) = Pricing(loan.terms.pricing).isValidRefinance(loan, newPricingData, msg.sender);

ReceivedItem[] memory refinanceConsideration =
_mergeConsiderations(considerationPayment, carryPayment, additionalPayment);

refinanceConsideration = _removeZeroAmounts(refinanceConsideration);

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

_settle(loan);

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

if (
ConduitInterface(conduit).execute(_packageTransfers(refinanceConsideration, msg.sender))
!= ConduitInterface.execute.selector
) {
revert ConduitTransferError();
}

loan.terms.pricingData = newPricingData;
loan.originator = msg.sender;
loan.issuer = msg.sender;
loan.start = block.timestamp;
_issueLoanManager(loan, msg.sender.code.length > 0);
}

receive() external payable {}
}
83 changes: 79 additions & 4 deletions src/lib/StarPortLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ library StarPortLib {
error InvalidSalt();

uint256 internal constant _INVALID_SALT = 0x81e69d9b00000000000000000000000000000000000000000000000000000000;
uint256 internal constant _RECEIVED_ITEM_RECIPIENT_OFFSET = 0x80;
uint256 internal constant _RECEIVED_ITEM_SIZE = 0xA0;

function getId(LoanManager.Loan memory loan) internal pure returns (uint256 loanId) {
loanId = uint256(keccak256(abi.encode(loan)));
Expand Down Expand Up @@ -39,12 +41,12 @@ library StarPortLib {
//store struct offsets - first offset starts at end of offsets
let o := s
let c := spentItems.offset
let r := add(s, 0x80) // first recipient offset
let r := add(s, _RECEIVED_ITEM_RECIPIENT_OFFSET) // first recipient offset
for {} lt(ptr, s) {
ptr := add(ptr, 0x20)
c := add(c, 0x80)
o := add(o, 0xA0)
r := add(r, 0xA0)
c := add(c, _RECEIVED_ITEM_RECIPIENT_OFFSET)
o := add(o, _RECEIVED_ITEM_SIZE)
r := add(r, _RECEIVED_ITEM_SIZE)
} {
mstore(ptr, o) //store offset
calldatacopy(o, c, 0x80)
Expand Down Expand Up @@ -91,5 +93,78 @@ library StarPortLib {
}
}

uint256 internal constant RECEIVED_AMOUNT_OFFSET = 0x60;

function _mergeAndRemoveZeroAmounts(
ReceivedItem[] memory repayConsideration,
ReceivedItem[] memory carryConsideration,
ReceivedItem[] memory additionalConsiderations,
uint256 validCount
) internal pure returns (ReceivedItem[] memory consideration) {
assembly {
function consumingCopy(arr, ptr) -> out {
let size := mload(arr)
let end := add(arr, mul(add(1, size), 0x20))
for { let i := add(0x20, arr) } lt(i, end) { i := add(i, 0x20) } {
let amount := mload(add(mload(i), RECEIVED_AMOUNT_OFFSET))
if iszero(amount) { continue }
mstore(ptr, mload(i))
ptr := add(ptr, 0x20)
}
//reset old array length
mstore(arr, 0)
out := ptr
}

//Set consideration to free memory
consideration := mload(0x40)
//Expand memory
mstore(0x40, add(add(0x20, consideration), mul(validCount, 0x20)))
mstore(consideration, validCount)
pop(
consumingCopy(
additionalConsiderations,
consumingCopy(carryConsideration, consumingCopy(repayConsideration, add(consideration, 0x20)))
)
)
}
}

function _countNonZeroAmounts(ReceivedItem[] memory arr, uint256 validCount) internal pure returns (uint256) {
assembly {
let size := mload(arr)
let i := add(arr, 0x20)
let end := add(i, mul(size, 0x20))
for {} lt(i, end) { i := add(i, 0x20) } {
let amount := mload(add(mload(i), RECEIVED_AMOUNT_OFFSET))
if iszero(amount) { continue }
validCount := add(validCount, 1)
}
}
return validCount;
}

function _mergeAndRemoveZeroAmounts(
ReceivedItem[] memory repayConsideration,
ReceivedItem[] memory carryConsideration,
ReceivedItem[] memory additionalConsiderations
) internal pure returns (ReceivedItem[] memory consideration) {
uint256 validCount = 0;
validCount = _countNonZeroAmounts(repayConsideration, validCount);
validCount = _countNonZeroAmounts(carryConsideration, validCount);
validCount = _countNonZeroAmounts(additionalConsiderations, validCount);
consideration =
_mergeAndRemoveZeroAmounts(repayConsideration, carryConsideration, additionalConsiderations, validCount);
}

function _mergeAndRemoveZeroAmounts(
ReceivedItem[] memory repayConsideration,
ReceivedItem[] memory carryConsideration
) internal pure returns (ReceivedItem[] memory consideration) {
uint256 validCount = 0;
validCount = _countNonZeroAmounts(repayConsideration, validCount);
validCount = _countNonZeroAmounts(carryConsideration, validCount);
consideration =
_mergeAndRemoveZeroAmounts(repayConsideration, carryConsideration, new ReceivedItem[](0), validCount);
}
}
45 changes: 8 additions & 37 deletions test/StarPortTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ import {TokenReceiverInterface} from "starport-core/interfaces/TokenReceiverInte
import {LoanSettledCallback} from "starport-core/LoanManager.sol";
import {ConduitHelper} from "starport-core/ConduitHelper.sol";


interface IWETH9 {
function deposit() external payable;

Expand Down Expand Up @@ -412,45 +411,17 @@ contract StarPortTest is BaseOrderTest, ConduitHelper {
}

function _executeRepayLoan(LoanManager.Loan memory activeLoan) internal {
(ReceivedItem[] memory loanPayment, ReceivedItem[] memory carryPayment) =
Pricing(activeLoan.terms.pricing).getPaymentConsideration(activeLoan);
uint256 i = 0;
ReceivedItem[] memory considerationPayments = _removeZeroAmounts(_mergeConsiderations(loanPayment, carryPayment, new ReceivedItem[](0)));
ConsiderationItem[] memory consider = new ConsiderationItem[](
considerationPayments.length
(SpentItem[] memory offer, ReceivedItem[] memory paymentConsideration) = Custodian(
payable(activeLoan.custodian)
).previewOrder(
address(LM.seaport()), activeLoan.borrower, new SpentItem[](0), new SpentItem[](0), abi.encode(activeLoan)
);


for (; i < consider.length;) {
consider[i].token = considerationPayments[i].token;
consider[i].itemType = considerationPayments[i].itemType;
consider[i].identifierOrCriteria = considerationPayments[i].identifier;
consider[i].startAmount = considerationPayments[i].amount;
//TODO: update this
consider[i].endAmount = considerationPayments[i].amount;
consider[i].recipient = considerationPayments[i].recipient;
unchecked {
++i;
}
}

OfferItem[] memory repayOffering = new OfferItem[](
activeLoan.collateral.length
OrderParameters memory op = _buildContractOrder(
address(custodian),
_SpentItemsToOfferItems(offer),
_toConsiderationItems(paymentConsideration)
);
i = 0;
for (; i < activeLoan.collateral.length;) {
repayOffering[i] = OfferItem({
itemType: activeLoan.collateral[i].itemType,
token: address(activeLoan.collateral[i].token),
identifierOrCriteria: activeLoan.collateral[i].identifier,
endAmount: activeLoan.collateral[i].itemType != ItemType.ERC721 ? activeLoan.collateral[i].amount : 1,
startAmount: activeLoan.collateral[i].itemType != ItemType.ERC721 ? activeLoan.collateral[i].amount : 1
});
unchecked {
++i;
}
}
OrderParameters memory op = _buildContractOrder(address(custodian), repayOffering, consider);

AdvancedOrder memory x = AdvancedOrder({
parameters: op,
Expand Down
65 changes: 65 additions & 0 deletions test/fuzz-testing/differential-fuzzing/TestConduitHelper.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
pragma solidity =0.8.17;

import "forge-std/Test.sol";
import {Vm} from "forge-std/Vm.sol";

import {ItemType, ReceivedItem, SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol";
import {
ConsiderationItem,
AdvancedOrder,
CriteriaResolver,
OrderType
} from "seaport-types/src/lib/ConsiderationStructs.sol";
import {Conduit} from "seaport-core/src/conduit/Conduit.sol";
import {ConduitController} from "seaport-core/src/conduit/ConduitController.sol";
import {StarPortLib} from "starport-core/lib/StarPortLib.sol";
import {ConduitHelper} from "starport-core/ConduitHelper.sol";
import {Bound} from "starport-test/utils/Bound.sol";
import {DeepEq} from "starport-test/utils/DeepEq.sol";
import {Cast} from "starport-test/utils/Cast.sol";
import "starport-test/utils/FuzzStructs.sol" as Fuzz;

contract TestContract is ConduitHelper {
function mergeConsiderations(ReceivedItem[] memory a, ReceivedItem[] memory b, ReceivedItem[] memory c)
public
pure
returns (ReceivedItem[] memory)
{
return _mergeConsiderations(a, b, c);
}
}

contract TestConduitHelper is Test, Bound, DeepEq {
TestContract testContract = new TestContract();
ReceivedItem[] receivedItems;

using Cast for *;

function testFuzzMergeConsiderations(
Fuzz.ReceivedItem[] memory a,
Fuzz.ReceivedItem[] memory b,
Fuzz.ReceivedItem[] memory c
) public {
ReceivedItem[] memory boundA = _boundReceivedItems(a);
ReceivedItem[] memory boundB = _boundReceivedItems(b);
ReceivedItem[] memory boundC = _boundReceivedItems(c);

testContract.mergeConsiderations(boundA, boundB, boundC).toStorage(receivedItems);

assertEq(receivedItems.length, a.length + b.length + c.length);
for (uint256 i = boundC.length; i > 0; --i) {
_deepEq(boundC[i - 1], receivedItems[receivedItems.length - 1]);
receivedItems.pop();
}
for (uint256 i = boundB.length; i > 0; --i) {
_deepEq(boundB[i - 1], receivedItems[receivedItems.length - 1]);
receivedItems.pop();
}

for (uint256 i = boundA.length; i > 0; --i) {
_deepEq(boundA[i - 1], receivedItems[receivedItems.length - 1]);
receivedItems.pop();
}
assertEq(receivedItems.length, 0);
}
}
Loading

0 comments on commit aba1c62

Please sign in to comment.