Skip to content

Commit

Permalink
fix: TestAstariaV1Loan fully working
Browse files Browse the repository at this point in the history
  • Loading branch information
dangerousfood committed Oct 26, 2023
1 parent 0867550 commit 956b298
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 318 deletions.
86 changes: 61 additions & 25 deletions src/handlers/AstariaV1SettlementHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {StarPortLib} from "starport-core/lib/StarPortLib.sol";
import {FixedPointMathLib} from "solady/src/utils/FixedPointMathLib.sol";
import "forge-std/console2.sol";
import {Pricing} from "starport-core/pricing/Pricing.sol";
import {BasePricing} from "starport-core/pricing/BasePricing.sol";

contract AstariaV1SettlementHandler is DutchAuctionHandler {
using {StarPortLib.getId} for LoanManager.Loan;
Expand Down Expand Up @@ -51,37 +52,72 @@ contract AstariaV1SettlementHandler is DutchAuctionHandler {
roundUp: true
});

(SpentItem[] memory paymentConsiderations, SpentItem[] memory carryFeeConsideration) =
Pricing(loan.terms.pricing).getPaymentConsideration(loan);
consideration = new ReceivedItem[](3);
uint256 i = 0;
BasePricing.Details memory pricingDetails = abi.decode(loan.terms.pricingData, (BasePricing.Details));
uint256 interest = BasePricing(loan.terms.pricing).getInterest(loan, pricingDetails.rate, loan.start, block.timestamp, 0);

// the settlementPrice does not cover carryFees
if (paymentConsiderations[0].amount <= settlementPrice) {
carryFeeConsideration = new SpentItem[](0);
uint256 carry = interest.mulWad(pricingDetails.carryRate);

if(loan.debt[0].amount + interest <= settlementPrice){
consideration[i] = ReceivedItem({
itemType: loan.debt[0].itemType,
identifier: loan.debt[0].identifier,
amount: carry,
token: loan.debt[0].token,
recipient: payable(loan.originator)
});
settlementPrice -= consideration[i].amount;
unchecked {
++i;
}
}
// the settlementPrice covers at least some of the carry fees
else {
carryFeeConsideration[0].amount =
settlementPrice - paymentConsiderations[0].amount - carryFeeConsideration[0].amount;
else if (loan.debt[0].amount + interest - carry <= settlementPrice) {
consideration[i] = ReceivedItem({
itemType: loan.debt[0].itemType,
identifier: loan.debt[0].identifier,
amount: (settlementPrice - loan.debt[0].amount + interest - carry),
token: loan.debt[0].token,
recipient: payable(loan.originator)
});
settlementPrice -= consideration[i].amount;
unchecked {
++i;
}
}
paymentConsiderations[0].amount = settlementPrice;

BaseRecall.Details memory hookDetails = abi.decode(loan.terms.hookData, (BaseRecall.Details));

uint256 recallerReward = (settlementPrice).mulWad(hookDetails.recallerRewardRatio);
if(recallerReward > 0){
consideration[i] = ReceivedItem({
itemType: loan.debt[0].itemType,
identifier: loan.debt[0].identifier,
amount: settlementPrice.mulWad(hookDetails.recallerRewardRatio),
token: loan.debt[0].token,
recipient: payable(recaller)
});
settlementPrice -= consideration[i].amount;
unchecked {
++i;
}
}

uint256 recallerReward = paymentConsiderations[0].amount.mulWad(hookDetails.recallerRewardRatio);

// recallerReward is taken directly from the repayment, carry is not subject to the recallerReward
paymentConsiderations[0].amount -= recallerReward;
ReceivedItem[] memory recallerPayment = new ReceivedItem[](1);
recallerPayment[0] = ReceivedItem({
itemType: paymentConsiderations[0].itemType,
identifier: paymentConsiderations[0].identifier,
amount: recallerReward,
token: paymentConsiderations[0].token,
recipient: payable(recaller)
consideration[i] = ReceivedItem({
itemType: loan.debt[0].itemType,
identifier: loan.debt[0].identifier,
amount: settlementPrice,
token: loan.debt[0].token,
recipient: payable(loan.issuer)
});

// TODO: fix this
// consideration = _mergeConsiderations(paymentConsiderations, carryFeeConsideration, recallerPayment);
consideration = _removeZeroAmounts(consideration);

unchecked {
++i;
}

assembly {
mstore(consideration, i)
}
}

function execute(LoanManager.Loan calldata loan, address fulfiller) external virtual override returns (bytes4) {
Expand Down
52 changes: 28 additions & 24 deletions src/hooks/BaseRecall.sol
Original file line number Diff line number Diff line change
Expand Up @@ -101,20 +101,22 @@ abstract contract BaseRecall is ConduitHelper {
revert RecallBeforeHoneymoonExpiry();
}

// get conduitController
(,, address conduitController) = seaport.information();
// validate that the provided conduit is owned by the msg.sender
if (ConduitControllerInterface(conduitController).ownerOf(conduit) != msg.sender) {
revert InvalidConduit();
}
ConduitTransfer[] memory recallConsideration =
_generateRecallConsideration(loan, 0, details.recallStakeDuration, 1e18, msg.sender, payable(address(this)));
if (
ConduitInterface(conduit).execute(recallConsideration)
!= ConduitInterface.execute.selector
) {
revert ConduitTransferError();
if(loan.issuer != msg.sender && loan.borrower != msg.sender){
(,, address conduitController) = seaport.information();
// validate that the provided conduit is owned by the msg.sender
if (ConduitControllerInterface(conduitController).ownerOf(conduit) != msg.sender) {
revert InvalidConduit();
}
ConduitTransfer[] memory recallConsideration =
_generateRecallConsideration(loan, 0, details.recallStakeDuration, 1e18, msg.sender, payable(address(this)));
if (
ConduitInterface(conduit).execute(recallConsideration)
!= ConduitInterface.execute.selector
) {
revert ConduitTransferError();
}
}
// get conduitController

bytes memory encodedLoan = abi.encode(loan);

Expand All @@ -140,19 +142,21 @@ abstract contract BaseRecall is ConduitHelper {
if (recall.start == 0 || recall.recaller == address(0)) {
revert WithdrawDoesNotExist();
}

if(loan.issuer != recall.recaller && loan.borrower != recall.recaller ){
ConduitTransfer[] memory recallConsideration =
_generateRecallConsideration(loan, 0, details.recallStakeDuration, 1e18, address(this), receiver);
recall.recaller = payable(address(0));
recall.start = 0;

ConduitTransfer[] memory recallConsideration =
_generateRecallConsideration(loan, 0, details.recallStakeDuration, 1e18, address(this), receiver);
recall.recaller = payable(address(0));
recall.start = 0;

for (uint256 i; i < recallConsideration.length;) {
if (loan.debt[i].itemType != ItemType.ERC20) revert InvalidStakeType();
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);
ERC20(loan.debt[i].token).transfer(receiver, recallConsideration[i].amount);

unchecked {
++i;
unchecked {
++i;
}
}
}

Expand All @@ -167,7 +171,7 @@ abstract contract BaseRecall is ConduitHelper {
BasePricing.Details memory details = abi.decode(loan.terms.pricingData, (BasePricing.Details));
recallStake = new uint256[](loan.debt.length);
for (uint256 i; i < loan.debt.length;) {
recallStake[i] = BasePricing(loan.terms.pricing).getInterest(loan, details, start, end, i);
recallStake[i] = BasePricing(loan.terms.pricing).getInterest(loan, details.rate, start, end, i);

unchecked {
++i;
Expand Down
91 changes: 4 additions & 87 deletions src/pricing/BasePricing.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,14 @@ abstract contract BasePricing is Pricing {
override
returns (SpentItem[] memory repayConsideration, SpentItem[] memory carryConsideration)
{
// repayConsideration = _generateRepayConsideration(loan);
// carryConsideration = _generateRepayCarryConsideration(loan);

Details memory details = abi.decode(loan.terms.pricingData, (Details));
if(details.carryRate > 0) carryConsideration = new SpentItem[](loan.debt.length);
else carryConsideration = new SpentItem[](0);
repayConsideration = new SpentItem[](loan.debt.length);

uint256 i=0;
for(;i<loan.debt.length;){
uint256 interest = getInterest(loan, details, loan.start, block.timestamp, i);
uint256 interest = getInterest(loan, details.rate, loan.start, block.timestamp, i);

if(details.carryRate > 0){
carryConsideration[i] = SpentItem({
Expand Down Expand Up @@ -88,48 +85,15 @@ abstract contract BasePricing is Pricing {

}

function getOwed(LoanManager.Loan memory loan) public view returns (uint256[] memory) {
Details memory details = abi.decode(loan.terms.pricingData, (Details));
return _getOwed(loan, details, loan.start, block.timestamp);
}

function _getOwedCarry(LoanManager.Loan memory loan, Details memory details, uint256 timestamp)
internal
view
returns (uint256[] memory carryOwed)
{
carryOwed = new uint256[](loan.debt.length);
uint256 i = 0;

for (; i < loan.debt.length;) {
uint256 carry = getInterest(loan, details, loan.start, timestamp, i).mulWad(details.carryRate);
carryOwed[i] = carry;
unchecked {
++i;
}
}
}

function _getOwed(LoanManager.Loan memory loan, Details memory details, uint256 start, uint256 end)
internal
view
returns (uint256[] memory updatedDebt)
{
updatedDebt = new uint256[](loan.debt.length);
for (uint256 i = 0; i < loan.debt.length; i++) {
updatedDebt[i] = loan.debt[i].amount + getInterest(loan, details, start, end, i);
}
}

function getInterest(
LoanManager.Loan memory loan,
Details memory details,
uint256 rate,
uint256 start,
uint256 end,
uint256 index
) public view returns (uint256) {
) public pure returns (uint256) {
uint256 delta_t = end - start;
return calculateInterest(delta_t, details.rate, loan.debt[index].amount);
return calculateInterest(delta_t, rate, loan.debt[index].amount);
}

function calculateInterest(
Expand All @@ -138,51 +102,4 @@ abstract contract BasePricing is Pricing {
uint256 rate // expressed as SPR seconds per rate
) public pure virtual returns (uint256);

function _generateRepayConsideration(LoanManager.Loan memory loan)
internal
view
returns (SpentItem[] memory consideration)
{
Details memory details = abi.decode(loan.terms.pricingData, (Details));

consideration = new SpentItem[](loan.debt.length);
uint256[] memory owing = _getOwed(loan, details, loan.start, block.timestamp);

uint256 i = 0;
for (; i < consideration.length;) {
consideration[i] = SpentItem({
itemType: loan.debt[i].itemType,
identifier: loan.debt[i].identifier,
amount: owing[i],
token: loan.debt[i].token
});
unchecked {
++i;
}
}
}

function _generateRepayCarryConsideration(LoanManager.Loan memory loan)
internal
view
returns (SpentItem[] memory consideration)
{
Details memory details = abi.decode(loan.terms.pricingData, (Details));

if (details.carryRate == 0) return new SpentItem[](0);
uint256[] memory owing = _getOwedCarry(loan, details, block.timestamp);
consideration = new SpentItem[](owing.length);
uint256 i = 0;
for (; i < consideration.length;) {
consideration[i] = SpentItem({
itemType: loan.debt[i].itemType,
identifier: loan.debt[i].identifier,
amount: owing[i],
token: loan.debt[i].token
});
unchecked {
++i;
}
}
}
}
Loading

0 comments on commit 956b298

Please sign in to comment.