Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/updates #25

Merged
merged 10 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 24 additions & 24 deletions .gas-snapshot
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
EnforcerTest:testCollateralEnforcer() (gas: 964781)
EnforcerTest:testFailCollateralEnforcerDifferentCollateral() (gas: 846753)
EnforcerTest:testFailRateEnforcerMaxCarryRate() (gas: 801907)
EnforcerTest:testFailRateEnforcerMaxRate() (gas: 801857)
EnforcerTest:testFailRateEnforcerMaxRateAndMaxCarryRate() (gas: 801722)
EnforcerTest:testRateEnforcerBasic() (gas: 922038)
EnforcerTest:testTermEnforcerBasic() (gas: 994300)
TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecall() (gas: 983680)
TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLender() (gas: 901571)
TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLiquidation() (gas: 948381)
EnforcerTest:testCollateralEnforcer() (gas: 964716)
EnforcerTest:testFailCollateralEnforcerDifferentCollateral() (gas: 846709)
EnforcerTest:testFailRateEnforcerMaxCarryRate() (gas: 801863)
EnforcerTest:testFailRateEnforcerMaxRate() (gas: 801813)
EnforcerTest:testFailRateEnforcerMaxRateAndMaxCarryRate() (gas: 801678)
EnforcerTest:testRateEnforcerBasic() (gas: 921973)
EnforcerTest:testTermEnforcerBasic() (gas: 994235)
TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecall() (gas: 983549)
TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLender() (gas: 901484)
TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLiquidation() (gas: 948294)
TestCustodian:testCustodySelector() (gas: 7152)
TestCustodian:testGenerateOrderRepay() (gas: 174179)
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: 224750)
TestCustodian:testPreviewOrderRepay() (gas: 224728)
TestCustodian:testPreviewOrderSettlement() (gas: 152470)
TestCustodian:testRatifyOrder() (gas: 188760)
TestCustodian:testRatifyOrder() (gas: 188738)
TestCustodian:testSafeTransferReceive() (gas: 159061)
TestCustodian:testSeaportMetadata() (gas: 8519)
TestCustodian:testSupportsInterface() (gas: 5791)
TestExoticLoans:testSwap() (gas: 1163700)
TestExoticLoans:testSwap() (gas: 1163635)
TestLoanCombinations:testLoan20For721SimpleInterestDutchFixedRepay() (gas: 252)
TestLoanCombinations:testLoan20for20SimpleInterestDutchFixedRepay() (gas: 517630)
TestLoanCombinations:testLoan721for20SimpleInterestDutchFixedRepay() (gas: 749358)
TestLoanCombinations:testLoanAstariaSettlementRepay() (gas: 515545)
TestLoanCombinations:testLoanSimpleInterestEnglishFixed() (gas: 735700)
TestLoanManager:testGenerateOrder() (gas: 1008482)
TestLoanCombinations:testLoan20for20SimpleInterestDutchFixedRepay() (gas: 517565)
TestLoanCombinations:testLoan721for20SimpleInterestDutchFixedRepay() (gas: 748890)
TestLoanCombinations:testLoanAstariaSettlementRepay() (gas: 515480)
TestLoanCombinations:testLoanSimpleInterestEnglishFixed() (gas: 735232)
TestLoanManager:testGenerateOrder() (gas: 1008458)
TestLoanManager:testGenerateOrderInvalidSender() (gas: 12986)
TestLoanManager:testSupportsInterface() (gas: 7003)
TestNewLoan:testBuyNowPayLater() (gas: 1146513)
TestNewLoan:testNewLoanERC721CollateralDefaultTerms2():((uint256,address,address,address,address,(uint8,address,uint256,uint256)[],(uint8,address,uint256,uint256)[],(address,bytes,address,bytes,address,bytes))) (gas: 993154)
TestNewLoan:testNewLoanERC721CollateralDefaultTermsRefinance() (gas: 653724)
TestNewLoan:testSettleLoan() (gas: 1274568)
TestRepayLoan:testRepayLoan() (gas: 732514)
TestNewLoan:testBuyNowPayLater() (gas: 1146962)
TestNewLoan:testNewLoanERC721CollateralDefaultTerms2():((uint256,address,address,address,address,(uint8,address,uint256,uint256)[],(uint8,address,uint256,uint256)[],(address,bytes,address,bytes,address,bytes))) (gas: 993089)
TestNewLoan:testNewLoanERC721CollateralDefaultTermsRefinance() (gas: 653637)
TestNewLoan:testSettleLoan() (gas: 1274481)
TestRepayLoan:testRepayLoan() (gas: 732046)
TestStarLiteUtils:testEncodeReceivedWithRecipient() (gas: 17955)
TestStarLiteUtils:testSpentToReceived() (gas: 17708)
TestStarLiteUtils:testValidateSaltOpt(address,bytes32) (runs: 256, μ: 26479, ~: 26479)
Expand Down
19 changes: 15 additions & 4 deletions .slither.config.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
{
"solc_remaps": [
"solady/=./lib/solady/",
"ds-test/=./lib/ds-test/src/",
"openzeppelin/=./lib/openzeppelin-contracts/contracts/",
"seaport/=./lib/seaport/contracts/"
"@openzeppelin/=lib/seaport/lib/openzeppelin-contracts/",
"@rari-capital/solmate/=lib/seaport/lib/solmate/",
"ds-test/=lib/seaport/lib/ds-test/src/",
"erc4626-tests/=lib/seaport/lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"murky/=lib/seaport/lib/murky/src/",
"openzeppelin-contracts/=lib/seaport/lib/openzeppelin-contracts/",
"seaport-core/=lib/seaport/lib/seaport-core/",
"seaport-sol/=lib/seaport/lib/seaport-sol/",
"seaport-types/=lib/seaport/lib/seaport-types/",
"seaport/=lib/seaport/",
"solady/=lib/solady/",
"solarray/=lib/seaport/lib/solarray/src/",
"solmate/=lib/solmate/src/",
"starport-core/=src/"
]
}
20 changes: 15 additions & 5 deletions remappings.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
solady/=lib/solady/
seaport/=lib/seaport/
seaport-types/=lib/seaport/lib/seaport-types/
@openzeppelin/=lib/seaport/lib/openzeppelin-contracts/
@rari-capital/solmate/=lib/seaport/lib/solmate/
ds-test/=lib/seaport/lib/ds-test/src/
erc4626-tests/=lib/seaport/lib/openzeppelin-contracts/lib/erc4626-tests/
forge-std/=lib/forge-std/src/
murky/=lib/seaport/lib/murky/src/
openzeppelin-contracts/=lib/seaport/lib/openzeppelin-contracts/
seaport-core/=lib/seaport/lib/seaport-core/
starport-core/=src
@chainlink/contracts/=node_modules/@chainlink/contracts/
seaport-sol/=lib/seaport/lib/seaport-sol/
seaport-types/=lib/seaport/lib/seaport-types/
seaport/=lib/seaport/
solady/=lib/solady/
solarray/=lib/seaport/lib/solarray/src/
solmate/=lib/solmate/src/
starport-core/=src/
starport-test/=test/
34 changes: 17 additions & 17 deletions src/Custodian.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import {ERC721} from "solady/src/tokens/ERC721.sol";
import {ERC20} from "solady/src/tokens/ERC20.sol";
import {ERC1155} from "solady/src/tokens/ERC1155.sol";

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

import {ContractOffererInterface} from "seaport/lib/seaport-types/src/interfaces/ContractOffererInterface.sol";
import {ContractOffererInterface} from "seaport-types/src/interfaces/ContractOffererInterface.sol";
import {TokenReceiverInterface} from "starport-core/interfaces/TokenReceiverInterface.sol";
import {FixedPointMathLib} from "solady/src/utils/FixedPointMathLib.sol";
import {Originator} from "starport-core/originators/Originator.sol";
Expand All @@ -25,11 +25,6 @@ contract Custodian is ContractOffererInterface, TokenReceiverInterface, ConduitH

mapping(address => mapping(address => bool)) public repayApproval;

function setRepayApproval(address payer, bool approved) external {
repayApproval[msg.sender][payer] = approved;
emit RepayApproval(msg.sender, payer, approved);
}

event RepayApproval(address borrower, address repayer, bool approved);
event SeaportCompatibleContractDeployed();

Expand All @@ -49,16 +44,6 @@ contract Custodian is ContractOffererInterface, TokenReceiverInterface, ConduitH
return _exists(loanId) ? ownerOf(loanId) : loan.borrower;
}

function mint(LoanManager.Loan calldata loan) external {
bytes memory encodedLoan = abi.encode(loan);
uint256 loanId = uint256(keccak256(encodedLoan));
if (loan.custodian != address(this) || !LM.issued(loanId)) {
revert("Custodian: Invalid loan"); //setup with proper error
}

_safeMint(loan.issuer, loanId, encodedLoan);
}

function tokenURI(uint256 tokenId) public view override returns (string memory) {
if (!_exists(tokenId)) {
revert("Custodian: Invalid token id");
Expand Down Expand Up @@ -95,6 +80,21 @@ contract Custodian is ContractOffererInterface, TokenReceiverInterface, ConduitH

//EXTERNAL FUNCTIONS

function mint(LoanManager.Loan calldata loan) external {
bytes memory encodedLoan = abi.encode(loan);
uint256 loanId = uint256(keccak256(encodedLoan));
if (loan.custodian != address(this) || !LM.issued(loanId)) {
revert("Custodian: Invalid loan"); //setup with proper error
}

_safeMint(loan.issuer, loanId, encodedLoan);
}

function setRepayApproval(address who, bool approved) external {
repayApproval[msg.sender][who] = approved;
emit RepayApproval(msg.sender, who, approved);
}

/**
* @dev Generates the order for this contract offerer.
*
Expand Down
84 changes: 46 additions & 38 deletions src/LoanManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -263,40 +263,52 @@ contract LoanManager is ERC721, ContractOffererInterface, ConduitHelper, Ownable
*
* @param caller The address of the contract fulfiller.
* @param fulfiller The address of the contract fulfiller.
* @param minimumReceived The minimum the fulfiller must receive.
* @param maximumSpent The most a fulfiller will spend
* @param minimumReceivedFromBorrower The minimum the fulfiller must receive.
* @param maximumSpentFromBorrower The most a fulfiller will spend
* @param context The context of the order.
* @return offer The items spent by the order.
* @return consideration The items received by the order.
*/
function previewOrder(
address caller,
address fulfiller,
SpentItem[] calldata minimumReceived,
SpentItem[] calldata maximumSpent,
SpentItem[] calldata minimumReceivedFromBorrower,
SpentItem[] calldata maximumSpentFromBorrower,
bytes calldata context // encoded based on the schemaID
) public view returns (SpentItem[] memory offer, ReceivedItem[] memory consideration) {
function(
address,
SpentItem[] calldata,
bytes calldata,
bool
) internal view returns (SpentItem[] memory, ReceivedItem[] memory) fn;
function(
address,
SpentItem[] calldata,
bytes calldata,
bool
)
internal
returns (
SpentItem[] memory,
ReceivedItem[] memory
) fn2 = _fillObligationAndVerify;
assembly {
fn := fn2
LoanManager.Obligation memory obligation = abi.decode(context, (LoanManager.Obligation));

if (obligation.debt.length == 0) {
revert InvalidDebt();
}
if (maximumSpentFromBorrower.length == 0) {
revert InvalidMaximumSpentEmpty();
}
consideration = maximumSpentFromBorrower.toReceivedItems(obligation.custodian);
if (feeTo != address(0)) {
consideration = _mergeFees(consideration, _feeRake(obligation.debt));
}
address receiver = obligation.borrower;

// we settle via seaport channels if caveats are present
if (fulfiller != receiver || obligation.caveats.length > 0) {
SpentItem[] memory debt = obligation.debt;
offer = new SpentItem[](debt.length + 1);

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

offer[debt.length] = SpentItem({
itemType: ItemType.ERC721,
token: address(this),
identifier: uint256(keccak256(abi.encode(obligation.caveats))),
amount: 1
});
}
(offer, consideration) = fn(fulfiller, maximumSpent, context, false);
}

/**
Expand All @@ -314,10 +326,10 @@ contract LoanManager is ERC721, ContractOffererInterface, ConduitHelper, Ownable
struct Fee {
ItemType itemType;
address token;
uint96 rake;
uint88 rake;
}

function setFeeData(address feeTo_, uint96 defaultFeeRake_) external onlyOwner {
function setFeeData(address feeTo_, uint88 defaultFeeRake_) external onlyOwner {
feeTo = feeTo_;
defaultFeeRake = defaultFeeRake_;
}
Expand Down Expand Up @@ -346,7 +358,7 @@ contract LoanManager is ERC721, ContractOffererInterface, ConduitHelper, Ownable
Fee memory fee = getExoticFee(debt[i]);
feeConsideration[i].itemType = fee.itemType;
feeConsideration[i].token = fee.token;
feeConsideration[i].amount = fee.rake;
feeConsideration[i].amount = fee.rake; //flat fee
}
unchecked {
++i;
Expand Down Expand Up @@ -378,8 +390,7 @@ contract LoanManager is ERC721, ContractOffererInterface, ConduitHelper, Ownable
function _fillObligationAndVerify(
address fulfiller,
SpentItem[] calldata maximumSpentFromBorrower,
bytes calldata context,
bool withEffects
bytes calldata context
) internal returns (SpentItem[] memory offer, ReceivedItem[] memory consideration) {
LoanManager.Obligation memory obligation = abi.decode(context, (LoanManager.Obligation));

Expand Down Expand Up @@ -418,18 +429,18 @@ contract LoanManager is ERC721, ContractOffererInterface, ConduitHelper, Ownable
debt: obligation.debt,
terms: response.terms
});

// we settle via seaport channels if caveats are present

if (enforceCaveats) {
bytes32 caveatHash = keccak256(
encodeWithSaltAndBorrowerCounter(
obligation.borrower, obligation.salt, keccak256(abi.encode(obligation.caveats))
)
);

//prevent replay on the salt
usedSalts.validateSalt(obligation.borrower, obligation.salt);

for (uint256 i = 0; i < obligation.caveats.length;) {
uint256 i = 0;
for (; i < obligation.caveats.length;) {
if (!CaveatEnforcer(obligation.caveats[i].enforcer).enforceCaveat(obligation.caveats[i].terms, loan)) {
revert InvalidOrigination();
}
Expand All @@ -439,10 +450,7 @@ contract LoanManager is ERC721, ContractOffererInterface, ConduitHelper, Ownable
}
offer = _setOffer(loan.debt, caveatHash);
}

if (withEffects) {
_issueLoanManager(loan, response.issuer.code.length > 0);
}
_issueLoanManager(loan, response.issuer.code.length > 0);
}

function _issueLoanManager(Loan memory loan, bool mint) internal {
Expand Down Expand Up @@ -472,7 +480,7 @@ contract LoanManager is ERC721, ContractOffererInterface, ConduitHelper, Ownable
SpentItem[] calldata maximumSpent,
bytes calldata context // encoded based on the schemaID
) external onlySeaport returns (SpentItem[] memory offer, ReceivedItem[] memory consideration) {
(offer, consideration) = _fillObligationAndVerify(fulfiller, maximumSpent, context, true);
(offer, consideration) = _fillObligationAndVerify(fulfiller, maximumSpent, context);
}

function _enableDebtWithSeaport(SpentItem memory debt) internal {
Expand Down
Loading