From 1b59637b13d4a766a16c2bef1c48acc9df34874e Mon Sep 17 00:00:00 2001 From: Joseph Delong Date: Wed, 18 Oct 2023 15:16:27 -0500 Subject: [PATCH] feat: extract Originator into a base abstract (#32) * feat: extract Originator into a base abstract * format & snapshot --------- Co-authored-by: 0xgregthedev <0xgregthedev@users.noreply.github.com> --- .gas-snapshot | 48 ++-- src/Custodian.sol | 1 - src/handlers/DutchAuctionHandler.sol | 1 - src/originators/Originator.sol | 199 +-------------- src/originators/PoolOriginator.sol | 141 ----------- src/originators/StrategistOriginator.sol | 229 ++++++++++++++++++ src/originators/UniqueOriginator.sol | 44 ---- test/StarPortTest.sol | 39 +-- .../integration-testing/TestAstariaV1Loan.sol | 18 +- test/integration-testing/TestNewLoan.sol | 34 +-- test/integration-testing/TestRepayLoan.sol | 6 +- test/unit-testing/TestCustodian.sol | 24 +- test/unit-testing/TestLoanManager.sol | 10 +- 13 files changed, 325 insertions(+), 469 deletions(-) delete mode 100644 src/originators/PoolOriginator.sol create mode 100644 src/originators/StrategistOriginator.sol delete mode 100644 src/originators/UniqueOriginator.sol diff --git a/.gas-snapshot b/.gas-snapshot index 670716fe..2d1da1eb 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,13 +1,13 @@ -EnforcerTest:testCollateralEnforcer() (gas: 950836) -EnforcerTest:testFailCollateralEnforcerDifferentCollateral() (gas: 832965) -EnforcerTest:testFailRateEnforcerMaxCarryRate() (gas: 788105) -EnforcerTest:testFailRateEnforcerMaxRate() (gas: 788077) -EnforcerTest:testFailRateEnforcerMaxRateAndMaxCarryRate() (gas: 787942) -EnforcerTest:testRateEnforcerBasic() (gas: 908012) -EnforcerTest:testTermEnforcerBasic() (gas: 980340) -TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecall() (gas: 969012) -TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLender() (gas: 859410) -TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLiquidation() (gas: 906274) +EnforcerTest:testCollateralEnforcer() (gas: 950647) +EnforcerTest:testFailCollateralEnforcerDifferentCollateral() (gas: 832776) +EnforcerTest:testFailRateEnforcerMaxCarryRate() (gas: 787916) +EnforcerTest:testFailRateEnforcerMaxRate() (gas: 787888) +EnforcerTest:testFailRateEnforcerMaxRateAndMaxCarryRate() (gas: 787753) +EnforcerTest:testRateEnforcerBasic() (gas: 907823) +EnforcerTest:testTermEnforcerBasic() (gas: 980151) +TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecall() (gas: 968823) +TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLender() (gas: 859221) +TestAstariaV1Loan:testNewLoanERC721CollateralDefaultTermsRecallLiquidation() (gas: 906085) TestCustodian:testCannotLazyMintTwice() (gas: 76591) TestCustodian:testCannotMintInvalidLoanInvalidCustodian() (gas: 66811) TestCustodian:testCannotMintInvalidLoanValidCustodian() (gas: 72394) @@ -16,9 +16,9 @@ TestCustodian:testDefaultCustodySelectorRevert() (gas: 11673) TestCustodian:testGenerateOrderInvalidHandlerExecution() (gas: 147388) TestCustodian:testGenerateOrderRepay() (gas: 189283) TestCustodian:testGenerateOrderRepayAsRepayApprovedBorrower() (gas: 214857) -TestCustodian:testGenerateOrderRepayERC1155AndERC20AndNative() (gas: 1130044) -TestCustodian:testGenerateOrderRepayERC1155AndERC20AndNativeHandlerAuthorized() (gas: 1029768) -TestCustodian:testGenerateOrderRepayERC1155WithRevert() (gas: 530761) +TestCustodian:testGenerateOrderRepayERC1155AndERC20AndNative() (gas: 1129477) +TestCustodian:testGenerateOrderRepayERC1155AndERC20AndNativeHandlerAuthorized() (gas: 1029201) +TestCustodian:testGenerateOrderRepayERC1155WithRevert() (gas: 530572) TestCustodian:testGenerateOrderRepayInvalidHookAddress() (gas: 104841) TestCustodian:testGenerateOrderRepayInvalidHookReturnType() (gas: 99244) TestCustodian:testGenerateOrderRepayNotBorrower() (gas: 110879) @@ -44,23 +44,23 @@ TestCustodian:testSupportsInterface() (gas: 9428) TestCustodian:testSymbol() (gas: 7105) TestCustodian:testTokenURI() (gas: 64811) TestCustodian:testTokenURIInvalidLoan() (gas: 13196) -TestExoticLoans:testSwap() (gas: 1353956) +TestExoticLoans:testSwap() (gas: 1353767) TestLoanCombinations:testLoan20For721SimpleInterestDutchFixedRepay() (gas: 164) -TestLoanCombinations:testLoan20for20SimpleInterestDutchFixedRepay() (gas: 539940) -TestLoanCombinations:testLoan721for20SimpleInterestDutchFixedRepay() (gas: 756253) -TestLoanCombinations:testLoanAstariaSettlementRepay() (gas: 575128) -TestLoanCombinations:testLoanSimpleInterestEnglishFixed() (gas: 747899) +TestLoanCombinations:testLoan20for20SimpleInterestDutchFixedRepay() (gas: 539789) +TestLoanCombinations:testLoan721for20SimpleInterestDutchFixedRepay() (gas: 756102) +TestLoanCombinations:testLoanAstariaSettlementRepay() (gas: 574976) +TestLoanCombinations:testLoanSimpleInterestEnglishFixed() (gas: 747748) TestLoanManager:testGenerateOrder() (gas: 1005642) TestLoanManager:testGenerateOrderNotSeaport() (gas: 13074) TestLoanManager:testName() (gas: 7206) TestLoanManager:testSupportsInterface() (gas: 9579) TestLoanManager:testSymbol() (gas: 7148) -TestNewLoan:testBuyNowPayLater() (gas: 1148671) -TestNewLoan:testNewLoanERC721CollateralDefaultTerms2():((uint256,address,address,address,address,(uint8,address,uint256,uint256)[],(uint8,address,uint256,uint256)[],(address,bytes,address,bytes,address,bytes))) (gas: 979121) -TestNewLoan:testNewLoanERC721CollateralDefaultTermsRefinance() (gas: 639892) -TestNewLoan:testNewLoanERC721CollateralLessDebtThanOffered():((uint256,address,address,address,address,(uint8,address,uint256,uint256)[],(uint8,address,uint256,uint256)[],(address,bytes,address,bytes,address,bytes))) (gas: 979455) -TestNewLoan:testSettleLoan() (gas: 1233583) -TestRepayLoan:testRepayLoan() (gas: 694754) +TestNewLoan:testBuyNowPayLater() (gas: 1141742) +TestNewLoan:testNewLoanERC721CollateralDefaultTerms2():((uint256,address,address,address,address,(uint8,address,uint256,uint256)[],(uint8,address,uint256,uint256)[],(address,bytes,address,bytes,address,bytes))) (gas: 978940) +TestNewLoan:testNewLoanERC721CollateralDefaultTermsRefinance() (gas: 639711) +TestNewLoan:testNewLoanERC721CollateralLessDebtThanOffered():((uint256,address,address,address,address,(uint8,address,uint256,uint256)[],(uint8,address,uint256,uint256)[],(address,bytes,address,bytes,address,bytes))) (gas: 979274) +TestNewLoan:testSettleLoan() (gas: 1233410) +TestRepayLoan:testRepayLoan() (gas: 694565) TestStarLiteUtils:testEncodeReceivedWithRecipient() (gas: 17955) TestStarLiteUtils:testSpentToReceived() (gas: 17708) TestStarLiteUtils:testValidateSaltOpt(address,bytes32) (runs: 256, μ: 26479, ~: 26479) diff --git a/src/Custodian.sol b/src/Custodian.sol index d4b553d5..8e12fea8 100644 --- a/src/Custodian.sol +++ b/src/Custodian.sol @@ -30,7 +30,6 @@ import {ContractOffererInterface} from "seaport-types/src/interfaces/ContractOff import {ConduitHelper} from "starport-core/ConduitHelper.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"; import {SettlementHook} from "starport-core/hooks/SettlementHook.sol"; import {SettlementHandler} from "starport-core/handlers/SettlementHandler.sol"; import {Pricing} from "starport-core/pricing/Pricing.sol"; diff --git a/src/handlers/DutchAuctionHandler.sol b/src/handlers/DutchAuctionHandler.sol index 868357bf..64d1f2ea 100644 --- a/src/handlers/DutchAuctionHandler.sol +++ b/src/handlers/DutchAuctionHandler.sol @@ -8,7 +8,6 @@ import { OrderParameters } from "seaport-types/src/lib/ConsiderationStructs.sol"; -import {Originator} from "starport-core/originators/Originator.sol"; import {Pricing} from "starport-core/pricing/Pricing.sol"; import {AmountDeriver} from "seaport-core/src/lib/AmountDeriver.sol"; import {FixedPointMathLib} from "solady/src/utils/FixedPointMathLib.sol"; diff --git a/src/originators/Originator.sol b/src/originators/Originator.sol index b57ea484..77ec41c6 100644 --- a/src/originators/Originator.sol +++ b/src/originators/Originator.sol @@ -22,31 +22,16 @@ pragma solidity =0.8.17; import {LoanManager} from "starport-core/LoanManager.sol"; -import {ItemType, ReceivedItem, SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; +import {SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; import {ConduitTransfer, ConduitItemType} from "seaport-types/src/conduit/lib/ConduitStructs.sol"; -import {ConduitControllerInterface} from "seaport-types/src/interfaces/ConduitControllerInterface.sol"; -import {ConduitInterface} from "seaport-types/src/interfaces/ConduitInterface.sol"; - -import {ECDSA} from "solady/src/utils/ECDSA.sol"; -import {SignatureCheckerLib} from "solady/src/utils/SignatureCheckerLib.sol"; import {Ownable} from "solady/src/auth/Ownable.sol"; -// Validator abstract contract that lays out the necessary structure and functions for the validator abstract contract Originator is Ownable { - enum State { - INITIALIZED, - CLOSED - } - struct Response { LoanManager.Terms terms; address issuer; } - event StrategistTransferred(address newStrategist); - - mapping(bytes32 => bool) public usedHashes; - struct Request { address custodian; address receiver; @@ -56,79 +41,9 @@ abstract contract Originator is Ownable { bytes approval; } - struct Details { - address custodian; - address conduit; - address issuer; - uint256 deadline; - Offer offer; - } - - struct Offer { - bytes32 salt; //can be bytes32(0) if so do not invalidate the hash - LoanManager.Terms terms; - SpentItem[] collateral; - SpentItem[] debt; - } - event Origination(uint256 indexed loanId, address indexed issuer, bytes nlrDetails); - event CounterUpdated(); - - event HashInvalidated(bytes32 hash); - - modifier onlyLoanManager() { - if (msg.sender != address(LM)) { - revert NotLoanManager(); - } - _; - } - - error NotLoanManager(); - error NotAuthorized(); - error InvalidDebt(); - error InvalidDebtLength(); - error InvalidDebtAmount(); - error InvalidCustodian(); - error InvalidCollateral(); - error InvalidDeadline(); - error InvalidOffer(); - error InvalidSigner(); - error ConduitTransferError(); - - LoanManager public immutable LM; - - // Define the EIP712 domain and typehash constants for generating signatures - bytes32 constant EIP_DOMAIN = keccak256("EIP712Domain(string version,uint256 chainId,address verifyingContract)"); - bytes32 public constant ORIGINATOR_DETAILS_TYPEHASH = keccak256("Origination(uint256 nonce,bytes32 hash)"); - bytes32 constant VERSION = keccak256("0"); - - bytes32 internal immutable _DOMAIN_SEPARATOR; - - // Strategist address and fee - address public strategist; - uint256 public strategistFee; - uint256 private _counter; - - constructor(LoanManager LM_, address strategist_, uint256 fee_, address owner) { - _initializeOwner(owner); - strategist = strategist_; - strategistFee = fee_; - LM = LM_; - _DOMAIN_SEPARATOR = keccak256( - abi.encode( - EIP_DOMAIN, - VERSION, //version - block.chainid, - address(this) - ) - ); - } - - function setStrategist(address newStrategist) external onlyOwner { - strategist = newStrategist; - emit StrategistTransferred(newStrategist); - } + function execute(Request calldata params) external virtual returns (Response memory response); function _packageTransfers(SpentItem[] memory loan, address borrower, address issuer) internal @@ -162,114 +77,4 @@ abstract contract Originator is Ownable { } } } - - function terms(bytes calldata details) public view virtual returns (LoanManager.Terms memory) { - return abi.decode(details, (Details)).offer.terms; - } - - function execute(Request calldata params) external 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}); - } - - // Encode the data with the account's nonce for generating a signature - function encodeWithAccountCounter(bytes32 contextHash) public view virtual returns (bytes memory) { - bytes32 hash = keccak256(abi.encode(ORIGINATOR_DETAILS_TYPEHASH, _counter, contextHash)); - - return abi.encodePacked(bytes1(0x19), bytes1(0x01), _DOMAIN_SEPARATOR, hash); - } - - function getStrategistData() public view virtual returns (address, uint256) { - return (strategist, strategistFee); - } - - // Get the nonce of an account - function getCounter() public view virtual returns (uint256) { - return _counter; - } - - function incrementCounter() external { - if (msg.sender != strategist || msg.sender != owner()) { - revert NotAuthorized(); - } - _counter += uint256(blockhash(block.number - 1) << 0x80); - emit CounterUpdated(); - } - - // Function to generate the domain separator for signatures - function domainSeparator() public view virtual returns (bytes32) { - return _DOMAIN_SEPARATOR; - } - - function _validateAsk(Request calldata request, Details memory details) internal virtual { - if (keccak256(abi.encode(request.collateral)) != keccak256(abi.encode(details.offer.collateral))) { - revert InvalidCollateral(); - } - - //loop through collateral and check if the collateral is the same - - for (uint256 i = 0; i < request.collateral.length;) { - if ( - request.debt[i].itemType != details.offer.debt[i].itemType - || request.debt[i].token != details.offer.debt[i].token - || request.debt[i].identifier != details.offer.debt[i].identifier - ) { - revert InvalidDebt(); - } - - if ( - request.debt[i].amount > details.offer.debt[i].amount || request.debt[i].amount == 0 - || details.offer.debt[i].amount == 0 - ) { - revert InvalidDebtAmount(); - } - unchecked { - i++; - } - } - } - - function _validateOffer(Request calldata request, Details memory details) internal virtual { - bytes32 contextHash = keccak256(request.details); - _validateSignature(keccak256(encodeWithAccountCounter(keccak256(request.details))), request.approval); - if (request.custodian != details.custodian) { - revert InvalidCustodian(); - } - if (request.debt.length != details.offer.debt.length) { - revert InvalidDebtLength(); - } - _validateAsk(request, details); - - if (details.offer.salt != bytes32(0)) { - if (!usedHashes[contextHash]) { - usedHashes[contextHash] = true; - emit HashInvalidated(contextHash); - } else { - revert InvalidOffer(); - } - } - if (block.timestamp > details.deadline) { - revert InvalidDeadline(); - } - } - - function _execute(Request calldata request, Details memory details) internal virtual { - if ( - ConduitInterface(details.conduit).execute(_packageTransfers(request.debt, request.receiver, details.issuer)) - != ConduitInterface.execute.selector - ) { - revert ConduitTransferError(); - } - } - - function _validateSignature(bytes32 hash, bytes memory signature) internal view virtual { - if (!SignatureCheckerLib.isValidSignatureNow(strategist, hash, signature)) { - revert InvalidSigner(); - } - } } diff --git a/src/originators/PoolOriginator.sol b/src/originators/PoolOriginator.sol deleted file mode 100644 index 4dbdf216..00000000 --- a/src/originators/PoolOriginator.sol +++ /dev/null @@ -1,141 +0,0 @@ -//pragma solidity =0.8.17; -//import "starport-core/originators/Originator.sol"; -// -//import {LoanManager} from "starport-core/LoanManager.sol"; -//import {ERC4626} from "solady/src/tokens/ERC4626.sol"; -// -//contract PoolOriginator is Originator { -// error InvalidLoan(); -// error InvalidTerms(); -// error InvalidDebtLength(); -// error ConduitTransferError(); -// -// constructor( -// LoanManager LM_, -// address strategist_, -// uint256 fee_ -// ) Originator(LM_, strategist_, fee_) {} -// -// struct Details { -// address conduit; -// address issuer; -// uint256 deadline; -// LoanManager.Terms terms; -// SpentItem[] collateral; -// SpentItem debt; -// } -// -// function execute( -// ExecuteParams calldata params -// ) external override returns (address issuer) { -// bytes32 contextHash = keccak256(params.nlrDetails); -// -// _validateSignature( -// keccak256(encodeWithAccountCounter(strategist, contextHash)), -// params.signature -// ); -// Details memory details = abi.decode(params.nlrDetails, (Details)); -// LoanManager.Loan calldata loan = params.loan; -// -// if (block.timestamp > details.deadline) { -// revert InvalidDeadline(); -// } -// -// if (loan.debt.length > 1) { -// revert InvalidDebtLength(); -// } -// -// // bool[] memory found = new bool[](loan.collateral.length); -// // uint256 matchCount = 0; -// // uint256 length = loan.collateral.length; -// // uint256 detailsLength = details.collateral.length; -// // uint i = 0; -// // uint j = 0; -// // for (; i < length; i++) { -// // if (matchCount == loan.collateral.length) { -// // break; -// // } -// // for (; j < detailsLength; j++) { -// // if ( -// // !found[i] && matchCount != loan.collateral[i].length && details.collateral[j].identifier != 0 && loan.collateral[i].identifier != 0 && -// // loan.collateral[i].itemType == details.collateral[j].itemType && -// // loan.collateral[i].token == details.collateral[j].token && -// // loan.collateral[i].identifier == details.collateral[j].identifier && -// // loan.collateral[i].amount < details.collateral[j].amount && -// // -// // ) { -// // found[i] = true; -// // matchCount++; -// // if (matchCount == loan.collateral.length) { -// // break; -// // } -// // } -// // } -// // } -// // if (matchCount != loan.collateral.length) { -// // revert InvalidCollateral(); -// // } -// // -// // found = new bool[](loan.debt.length); -// // matchCount = 0; -// // length = loan.debt.length; -// // detailsLength = details.debt.length; -// // i = 0; -// // j = 0; -// // // for (; i < length; i++) { -// // // for (; j < detailsLength; j++) { -// // // if ( -// // // loan.debt[i].itemType == details.debt[j].itemType && -// // // loan.debt[i].token == details.debt[j].token && -// // // loan.debt[i].identifier != 0 && -// // // loan.debt[i].identifier == details.debt[j].identifier && -// // // loan.debt[i].amount < details.debt[j].amount && -// // // !found[i] -// // // ) { -// // // found[i] = true; -// // // matchCount++; -// // // } -// // // if (matchCount == loan.debt.length) { -// // // break; -// // // } -// // // } -// // // } -// // -// if ( -// // keccak256(abi.encode(loan.collateral)) != -// // keccak256(abi.encode(details.collateral)) || -// keccak256(abi.encode(loan.terms)) != keccak256(abi.encode(details.terms)) -// ) { -// revert InvalidTerms(); -// } -// -// if ( -// ConduitInterface.execute.selector != -// ConduitInterface(details.conduit).execute( -// _packageTransfers(loan, details.issuer) -// ) -// ) { -// revert ConduitTransferError(); -// } -// // emit Origination(params.loanId, details.issuer, params.nlrDetails); -// //the recipient is the issuer since we reuse the struct -// // LoanManager(msg.sender).mint(loan, details.issuer); -// // selector = Originator.execute.selector; -// issuer = details.issuer; -// } -// -// event Origination( -// uint256 indexed loanId, -// address indexed issuer, -// bytes nlrDetails -// ); -// -// enum State { -// INITIALIZED, -// CLOSED -// } -// -// function getFeeConsideration( -// LoanManager.Loan calldata loan -// ) external view override returns (ReceivedItem memory consideration) {} -//} diff --git a/src/originators/StrategistOriginator.sol b/src/originators/StrategistOriginator.sol new file mode 100644 index 00000000..f484e929 --- /dev/null +++ b/src/originators/StrategistOriginator.sol @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: BUSL-1.1 +/** + * ,--, + * ,---.'| + * ,----.. ,---, ,-. | | : + * / / \ ,--.' | ,--, ,--/ /| : : | ,---, + * | : :| | : ,--.'| ,---, .---. ,---. __ ,-.,--. :/ | | ' : ,---.'| + * . | ;. /: : : | |, ,-+-. / | /. ./| ' ,'\ ,' ,'/ /|: : ' / .--.--. ; ; ' | | : .--.--. + * . ; /--` : | |,--. ,--.--. `--'_ ,--.'|' | .-'-. ' | / / |' | |' || ' / / / ' ' | |__ ,--.--. : : : / / ' + * ; | ; | : ' | / \ ,' ,'| | | ,"' | /___/ \: |. ; ,. :| | ,'' | : | : /`./ | | :.'| / \ : |,-.| : /`./ + * | : | | | /' :.--. .-. | ' | | | | / | | .-'.. ' ' .' | |: :' : / | | \| : ;_ ' : ;.--. .-. | | : ' || : ;_ + * . | '___ ' : | | | \__\/: . . | | : | | | | |/___/ \: '' | .; :| | ' ' : |. \\ \ `. | | ./ \__\/: . . | | / : \ \ `. + * ' ; : .'|| | ' | : ," .--.; | ' : |__ | | | |/ . \ ' .\ | : |; : | | | ' \ \`----. \ ; : ; ," .--.; | ' : |: | `----. \ + * ' | '/ :| : :_:,'/ / ,. | | | '.'|| | |--' \ \ ' \ | \ \ / | , ; ' : |--'/ /`--' / | ,/ / / ,. | | | '/ : / /`--' / + * | : / | | ,' ; : .' \; : ;| |/ \ \ |--" `----' ---' ; |,' '--'. / '---' ; : .' \| : |'--'. / + * \ \ .' `--'' | , .-./| , / '---' \ \ | '--' `--'---' | , .-.// \ / `--'---' + * `---` `--`---' ---`-' '---" `--`---' `-'----' + * + * Chainworks Labs + */ +pragma solidity =0.8.17; + +import {LoanManager} from "starport-core/LoanManager.sol"; + +import {ItemType, ReceivedItem, SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; +import {ConduitTransfer, ConduitItemType} from "seaport-types/src/conduit/lib/ConduitStructs.sol"; +import {ConduitControllerInterface} from "seaport-types/src/interfaces/ConduitControllerInterface.sol"; +import {ConduitInterface} from "seaport-types/src/interfaces/ConduitInterface.sol"; + +import {ECDSA} from "solady/src/utils/ECDSA.sol"; +import {SignatureCheckerLib} from "solady/src/utils/SignatureCheckerLib.sol"; +import {Ownable} from "solady/src/auth/Ownable.sol"; +import {Originator} from "starport-core/originators/Originator.sol"; + +// Validator abstract contract that lays out the necessary structure and functions for the validator +contract StrategistOriginator is Ownable, Originator { + event StrategistTransferred(address newStrategist); + + mapping(bytes32 => bool) public usedHashes; + + struct Details { + address custodian; + address conduit; + address issuer; + uint256 deadline; + Offer offer; + } + + struct Offer { + bytes32 salt; //can be bytes32(0) if so do not invalidate the hash + LoanManager.Terms terms; + SpentItem[] collateral; + SpentItem[] debt; + } + + event CounterUpdated(); + + event HashInvalidated(bytes32 hash); + + modifier onlyLoanManager() { + if (msg.sender != address(LM)) { + revert NotLoanManager(); + } + _; + } + + error NotLoanManager(); + error NotAuthorized(); + error InvalidDebt(); + error InvalidDebtLength(); + error InvalidDebtAmount(); + error InvalidCustodian(); + error InvalidCollateral(); + error InvalidDeadline(); + error InvalidOffer(); + error InvalidSigner(); + error ConduitTransferError(); + + LoanManager public immutable LM; + + // Define the EIP712 domain and typehash constants for generating signatures + bytes32 constant EIP_DOMAIN = keccak256("EIP712Domain(string version,uint256 chainId,address verifyingContract)"); + bytes32 public constant ORIGINATOR_DETAILS_TYPEHASH = keccak256("Origination(uint256 nonce,bytes32 hash)"); + bytes32 constant VERSION = keccak256("0"); + + bytes32 internal immutable _DOMAIN_SEPARATOR; + + // Strategist address and fee + address public strategist; + uint256 public strategistFee; + uint256 private _counter; + + constructor(LoanManager LM_, address strategist_, uint256 fee_, address owner) { + _initializeOwner(owner); + strategist = strategist_; + strategistFee = fee_; + LM = LM_; + _DOMAIN_SEPARATOR = keccak256( + abi.encode( + EIP_DOMAIN, + VERSION, //version + block.chainid, + address(this) + ) + ); + } + + function setStrategist(address newStrategist) external onlyOwner { + strategist = newStrategist; + emit StrategistTransferred(newStrategist); + } + + function _buildResponse(Request calldata params, Details memory details) + internal + virtual + returns (Response memory response) + { + response = Response({terms: details.offer.terms, issuer: details.issuer}); + } + + // Encode the data with the account's nonce for generating a signature + function encodeWithAccountCounter(bytes32 contextHash) public view virtual returns (bytes memory) { + bytes32 hash = keccak256(abi.encode(ORIGINATOR_DETAILS_TYPEHASH, _counter, contextHash)); + + return abi.encodePacked(bytes1(0x19), bytes1(0x01), _DOMAIN_SEPARATOR, hash); + } + + function getStrategistData() public view virtual returns (address, uint256) { + return (strategist, strategistFee); + } + + // Get the nonce of an account + function getCounter() public view virtual returns (uint256) { + return _counter; + } + + function incrementCounter() external { + if (msg.sender != strategist || msg.sender != owner()) { + revert NotAuthorized(); + } + _counter += uint256(blockhash(block.number - 1) << 0x80); + emit CounterUpdated(); + } + + // Function to generate the domain separator for signatures + function domainSeparator() public view virtual returns (bytes32) { + return _DOMAIN_SEPARATOR; + } + + function execute(Request calldata params) + external + virtual + override + onlyLoanManager + returns (Response memory response) + { + Details memory details = abi.decode(params.details, (Details)); + _validateOffer(params, details); + _execute(params, details); + response = _buildResponse(params, details); + } + + function _validateAsk(Request calldata request, Details memory details) internal virtual { + if (keccak256(abi.encode(request.collateral)) != keccak256(abi.encode(details.offer.collateral))) { + revert InvalidCollateral(); + } + + //loop through collateral and check if the collateral is the same + + for (uint256 i = 0; i < request.collateral.length;) { + if ( + request.debt[i].itemType != details.offer.debt[i].itemType + || request.debt[i].token != details.offer.debt[i].token + || request.debt[i].identifier != details.offer.debt[i].identifier + ) { + revert InvalidDebt(); + } + + if ( + request.debt[i].amount > details.offer.debt[i].amount || request.debt[i].amount == 0 + || details.offer.debt[i].amount == 0 + ) { + revert InvalidDebtAmount(); + } + unchecked { + i++; + } + } + } + + function _validateOffer(Request calldata request, Details memory details) internal virtual { + bytes32 contextHash = keccak256(request.details); + _validateSignature(keccak256(encodeWithAccountCounter(keccak256(request.details))), request.approval); + if (request.custodian != details.custodian) { + revert InvalidCustodian(); + } + if (request.debt.length != details.offer.debt.length) { + revert InvalidDebtLength(); + } + _validateAsk(request, details); + + if (details.offer.salt != bytes32(0)) { + if (!usedHashes[contextHash]) { + usedHashes[contextHash] = true; + emit HashInvalidated(contextHash); + } else { + revert InvalidOffer(); + } + } + if (block.timestamp > details.deadline) { + revert InvalidDeadline(); + } + } + + function _execute(Request calldata request, Details memory details) internal virtual { + if ( + ConduitInterface(details.conduit).execute(_packageTransfers(request.debt, request.receiver, details.issuer)) + != ConduitInterface.execute.selector + ) { + revert ConduitTransferError(); + } + } + + function _validateSignature(bytes32 hash, bytes memory signature) internal view virtual { + if (!SignatureCheckerLib.isValidSignatureNow(strategist, hash, signature)) { + revert InvalidSigner(); + } + } +} diff --git a/src/originators/UniqueOriginator.sol b/src/originators/UniqueOriginator.sol deleted file mode 100644 index 35c4d87b..00000000 --- a/src/originators/UniqueOriginator.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -/** - * ,--, - * ,---.'| - * ,----.. ,---, ,-. | | : - * / / \ ,--.' | ,--, ,--/ /| : : | ,---, - * | : :| | : ,--.'| ,---, .---. ,---. __ ,-.,--. :/ | | ' : ,---.'| - * . | ;. /: : : | |, ,-+-. / | /. ./| ' ,'\ ,' ,'/ /|: : ' / .--.--. ; ; ' | | : .--.--. - * . ; /--` : | |,--. ,--.--. `--'_ ,--.'|' | .-'-. ' | / / |' | |' || ' / / / ' ' | |__ ,--.--. : : : / / ' - * ; | ; | : ' | / \ ,' ,'| | | ,"' | /___/ \: |. ; ,. :| | ,'' | : | : /`./ | | :.'| / \ : |,-.| : /`./ - * | : | | | /' :.--. .-. | ' | | | | / | | .-'.. ' ' .' | |: :' : / | | \| : ;_ ' : ;.--. .-. | | : ' || : ;_ - * . | '___ ' : | | | \__\/: . . | | : | | | | |/___/ \: '' | .; :| | ' ' : |. \\ \ `. | | ./ \__\/: . . | | / : \ \ `. - * ' ; : .'|| | ' | : ," .--.; | ' : |__ | | | |/ . \ ' .\ | : |; : | | | ' \ \`----. \ ; : ; ," .--.; | ' : |: | `----. \ - * ' | '/ :| : :_:,'/ / ,. | | | '.'|| | |--' \ \ ' \ | \ \ / | , ; ' : |--'/ /`--' / | ,/ / / ,. | | | '/ : / /`--' / - * | : / | | ,' ; : .' \; : ;| |/ \ \ |--" `----' ---' ; |,' '--'. / '---' ; : .' \| : |'--'. / - * \ \ .' `--'' | , .-./| , / '---' \ \ | '--' `--'---' | , .-.// \ / `--'---' - * `---` `--`---' ---`-' '---" `--`---' `-'----' - * - * Chainworks Labs - */ -pragma solidity =0.8.17; - -import {LoanManager} from "starport-core/LoanManager.sol"; - -import "starport-core/originators/Originator.sol"; - -contract UniqueOriginator is Originator { - constructor(LoanManager LM_, address strategist_, uint256 fee_, address owner) - Originator(LM_, strategist_, fee_, owner) - {} - - function execute(Request calldata params) - external - virtual - override - onlyLoanManager - returns (Response memory response) - { - Details memory details = abi.decode(params.details, (Details)); - _validateOffer(params, details); - _execute(params, details); - response = _buildResponse(params, details); - } -} diff --git a/test/StarPortTest.sol b/test/StarPortTest.sol index 8e3ab641..6fb3176b 100644 --- a/test/StarPortTest.sol +++ b/test/StarPortTest.sol @@ -4,7 +4,7 @@ import "forge-std/Test.sol"; import {Vm} from "forge-std/Vm.sol"; import {LoanManager} from "starport-core/LoanManager.sol"; import {Pricing} from "starport-core/pricing/Pricing.sol"; -import {Originator} from "starport-core/originators/Originator.sol"; +import {StrategistOriginator} from "starport-core/originators/StrategistOriginator.sol"; import { ItemType, ReceivedItem, @@ -29,7 +29,7 @@ import {Consideration} from "seaport-core/src/lib/Consideration.sol"; //import { // ReferenceConsideration as Consideration //} from "seaport/reference/ReferenceConsideration.sol"; -import {UniqueOriginator} from "starport-core/originators/UniqueOriginator.sol"; +import {StrategistOriginator} from "starport-core/originators/StrategistOriginator.sol"; import {SimpleInterestPricing} from "starport-core/pricing/SimpleInterestPricing.sol"; import {CompoundInterestPricing} from "starport-core/pricing/CompoundInterestPricing.sol"; @@ -145,7 +145,7 @@ contract StarPortTest is BaseOrderTest { address seaportAddr; LoanManager LM; Custodian custodian; - UniqueOriginator UO; + StrategistOriginator SO; bytes32 conduitKeyRefinancer; @@ -187,7 +187,7 @@ contract StarPortTest is BaseOrderTest { LM = new LoanManager(consideration); custodian = Custodian(payable(LM.defaultCustodian())); - UO = new UniqueOriginator(LM, strategist.addr, 1e16, address(this)); + SO = new StrategistOriginator(LM, strategist.addr, 1e16, address(this)); pricing = new SimpleInterestPricing(LM); handler = new FixedTermDutchAuctionHandler(LM); hook = new FixedTermHook(); @@ -211,7 +211,7 @@ contract StarPortTest is BaseOrderTest { vm.startPrank(lender.addr); lenderConduit = conduitController.createConduit(conduitKeyOne, lender.addr); - conduitController.updateChannel(lenderConduit, address(UO), true); + conduitController.updateChannel(lenderConduit, address(SO), true); erc20s[0].approve(address(lenderConduit), 100000); vm.stopPrank(); vm.prank(address(issuer)); @@ -259,10 +259,11 @@ contract StarPortTest is BaseOrderTest { bytes details; } - function newLoan(NewLoanData memory loanData, Originator originator, ConsiderationItem[] storage collateral) - internal - returns (LoanManager.Loan memory) - { + function newLoan( + NewLoanData memory loanData, + StrategistOriginator originator, + ConsiderationItem[] storage collateral + ) internal returns (LoanManager.Loan memory) { bool isTrusted = loanData.caveats.length == 0; { bytes32 detailsHash = keccak256(originator.encodeWithAccountCounter(keccak256(loanData.details))); @@ -286,7 +287,7 @@ contract StarPortTest is BaseOrderTest { function buyNowPayLater( AdvancedOrder memory thingToBuy, NewLoanData memory loanData, - Originator originator, + StrategistOriginator originator, ConsiderationItem[] storage collateral ) internal { (uint8 v, bytes32 r, bytes32 s) = @@ -297,7 +298,7 @@ contract StarPortTest is BaseOrderTest { issuer: address(0), borrower: borrower.addr, originator: address(0), - terms: originator.terms(loanData.details), + terms: abi.decode(loanData.details, (StrategistOriginator.Details)).offer.terms, debt: debt, collateral: ConsiderationItemLib.toSpentItemArray(collateral), start: uint256(0) @@ -787,7 +788,7 @@ contract StarPortTest is BaseOrderTest { ConsiderationItem memory collateral, SpentItem memory debtRequested, address incomingIssuer - ) internal returns (Originator.Details memory details) { + ) internal returns (StrategistOriginator.Details memory details) { delete selectedCollateral; delete debt; selectedCollateral.push(collateral); @@ -800,12 +801,12 @@ contract StarPortTest is BaseOrderTest { handlerData: defaultHandlerData, hookData: defaultHookData }); - details = Originator.Details({ + details = StrategistOriginator.Details({ conduit: address(lenderConduit), custodian: address(custodian), issuer: incomingIssuer, deadline: block.timestamp + 100, - offer: Originator.Offer({ + offer: StrategistOriginator.Offer({ salt: bytes32(0), terms: terms, collateral: ConsiderationItemLib.toSpentItemArray(selectedCollateral), @@ -823,7 +824,7 @@ contract StarPortTest is BaseOrderTest { selectedCollateral.push(collateralItem); debt.push(debtItem); - Originator.Details memory loanDetails = _generateOriginationDetails(collateralItem, debtItem, lender); + StrategistOriginator.Details memory loanDetails = _generateOriginationDetails(collateralItem, debtItem, lender); loan = newLoan( NewLoanData({ @@ -831,7 +832,7 @@ contract StarPortTest is BaseOrderTest { caveats: new LoanManager.Caveat[](0), // TODO check details: abi.encode(loanDetails) }), - Originator(UO), + StrategistOriginator(SO), selectedCollateral ); } @@ -846,12 +847,12 @@ contract StarPortTest is BaseOrderTest { selectedCollateral.push(collateralItem); debt.push(debtItem); - Originator.Details memory loanDetails = Originator.Details({ + StrategistOriginator.Details memory loanDetails = StrategistOriginator.Details({ conduit: address(lenderConduit), custodian: address(custodian), issuer: lender, deadline: block.timestamp + 100, - offer: Originator.Offer({ + offer: StrategistOriginator.Offer({ salt: bytes32(0), terms: terms, collateral: ConsiderationItemLib.toSpentItemArray(selectedCollateral), @@ -865,7 +866,7 @@ contract StarPortTest is BaseOrderTest { caveats: caveats, // TODO check details: abi.encode(loanDetails) }), - Originator(UO), + StrategistOriginator(SO), selectedCollateral ); } diff --git a/test/integration-testing/TestAstariaV1Loan.sol b/test/integration-testing/TestAstariaV1Loan.sol index 8577fb3a..7d189dc0 100644 --- a/test/integration-testing/TestAstariaV1Loan.sol +++ b/test/integration-testing/TestAstariaV1Loan.sol @@ -33,12 +33,12 @@ contract TestAstariaV1Loan is AstariaV1Test { ); debt.push(SpentItem({itemType: ItemType.ERC20, token: address(erc20s[0]), amount: 100, identifier: 0})); - Originator.Details memory loanDetails = Originator.Details({ + StrategistOriginator.Details memory loanDetails = StrategistOriginator.Details({ conduit: address(lenderConduit), custodian: address(custody), issuer: lender.addr, deadline: block.timestamp + 100, - offer: Originator.Offer({ + offer: StrategistOriginator.Offer({ salt: bytes32(0), terms: terms, collateral: ConsiderationItemLib.toSpentItemArray(selectedCollateral), @@ -48,7 +48,7 @@ contract TestAstariaV1Loan is AstariaV1Test { LoanManager.Loan memory loan = newLoan( NewLoanData(address(custody), new LoanManager.Caveat[](0), abi.encode(loanDetails)), - Originator(UO), + StrategistOriginator(SO), selectedCollateral ); uint256 loanId = loan.getId(); @@ -202,12 +202,12 @@ contract TestAstariaV1Loan is AstariaV1Test { ); debt.push(SpentItem({itemType: ItemType.ERC20, token: address(erc20s[0]), amount: 100, identifier: 0})); - Originator.Details memory loanDetails = Originator.Details({ + StrategistOriginator.Details memory loanDetails = StrategistOriginator.Details({ conduit: address(lenderConduit), custodian: address(custody), issuer: lender.addr, deadline: block.timestamp + 100, - offer: Originator.Offer({ + offer: StrategistOriginator.Offer({ salt: bytes32(0), terms: terms, collateral: ConsiderationItemLib.toSpentItemArray(selectedCollateral), @@ -217,7 +217,7 @@ contract TestAstariaV1Loan is AstariaV1Test { LoanManager.Loan memory loan = newLoan( NewLoanData(address(custody), new LoanManager.Caveat[](0), abi.encode(loanDetails)), - Originator(UO), + StrategistOriginator(SO), selectedCollateral ); uint256 loanId = loan.getId(); @@ -343,12 +343,12 @@ contract TestAstariaV1Loan is AstariaV1Test { ); debt.push(SpentItem({itemType: ItemType.ERC20, token: address(erc20s[0]), amount: 100, identifier: 0})); - Originator.Details memory loanDetails = Originator.Details({ + StrategistOriginator.Details memory loanDetails = StrategistOriginator.Details({ conduit: address(lenderConduit), custodian: address(custody), issuer: lender.addr, deadline: block.timestamp + 100, - offer: Originator.Offer({ + offer: StrategistOriginator.Offer({ salt: bytes32(0), terms: terms, collateral: ConsiderationItemLib.toSpentItemArray(selectedCollateral), @@ -358,7 +358,7 @@ contract TestAstariaV1Loan is AstariaV1Test { LoanManager.Loan memory loan = newLoan( NewLoanData(address(custody), new LoanManager.Caveat[](0), abi.encode(loanDetails)), - Originator(UO), + StrategistOriginator(SO), selectedCollateral ); uint256 loanId = loan.getId(); diff --git a/test/integration-testing/TestNewLoan.sol b/test/integration-testing/TestNewLoan.sol index c1b1cd3b..6be73c48 100644 --- a/test/integration-testing/TestNewLoan.sol +++ b/test/integration-testing/TestNewLoan.sol @@ -26,12 +26,12 @@ contract TestNewLoan is StarPortTest { ); debt.push(SpentItem({itemType: ItemType.ERC20, token: address(erc20s[0]), amount: 100, identifier: 0})); - Originator.Details memory loanDetails = Originator.Details({ + StrategistOriginator.Details memory loanDetails = StrategistOriginator.Details({ conduit: address(lenderConduit), custodian: address(custody), issuer: lender.addr, deadline: block.timestamp + 100, - offer: Originator.Offer({ + offer: StrategistOriginator.Offer({ salt: bytes32(0), terms: terms, collateral: ConsiderationItemLib.toSpentItemArray(selectedCollateral), @@ -47,8 +47,11 @@ contract TestNewLoan is StarPortTest { LoanManager.Caveat[] memory caveats = new LoanManager.Caveat[](1); caveats[0] = LoanManager.Caveat({enforcer: address(TE), terms: abi.encode(TEDetails)}); - return - newLoan(NewLoanData(address(custody), caveats, abi.encode(loanDetails)), Originator(UO), selectedCollateral); + return newLoan( + NewLoanData(address(custody), caveats, abi.encode(loanDetails)), + StrategistOriginator(SO), + selectedCollateral + ); } function testNewLoanERC721CollateralLessDebtThanOffered() public returns (LoanManager.Loan memory) { @@ -75,12 +78,12 @@ contract TestNewLoan is StarPortTest { ); debt.push(SpentItem({itemType: ItemType.ERC20, token: address(erc20s[0]), amount: 100, identifier: 0})); - Originator.Details memory loanDetails = Originator.Details({ + StrategistOriginator.Details memory loanDetails = StrategistOriginator.Details({ conduit: address(lenderConduit), custodian: address(custody), issuer: lender.addr, deadline: block.timestamp + 100, - offer: Originator.Offer({ + offer: StrategistOriginator.Offer({ salt: bytes32(0), terms: terms, collateral: ConsiderationItemLib.toSpentItemArray(selectedCollateral), @@ -97,8 +100,11 @@ contract TestNewLoan is StarPortTest { LoanManager.Caveat[] memory caveats = new LoanManager.Caveat[](1); caveats[0] = LoanManager.Caveat({enforcer: address(TE), terms: abi.encode(TEDetails)}); - return - newLoan(NewLoanData(address(custody), caveats, abi.encode(loanDetails)), Originator(UO), selectedCollateral); + return newLoan( + NewLoanData(address(custody), caveats, abi.encode(loanDetails)), + StrategistOriginator(SO), + selectedCollateral + ); } function testNewLoanERC721CollateralDefaultTermsRefinance() public { @@ -126,12 +132,12 @@ contract TestNewLoan is StarPortTest { ); debt.push(SpentItem({itemType: ItemType.ERC20, token: address(erc20s[0]), amount: 100, identifier: 0})); - Originator.Details memory loanDetails = Originator.Details({ + StrategistOriginator.Details memory loanDetails = StrategistOriginator.Details({ conduit: address(lenderConduit), custodian: address(custody), issuer: lender.addr, deadline: block.timestamp + 100, - offer: Originator.Offer({ + offer: StrategistOriginator.Offer({ salt: bytes32(0), terms: terms, collateral: ConsiderationItemLib.toSpentItemArray(selectedCollateral), @@ -141,7 +147,7 @@ contract TestNewLoan is StarPortTest { LoanManager.Loan memory loan = newLoan( NewLoanData(address(custody), new LoanManager.Caveat[](0), abi.encode(loanDetails)), - Originator(UO), + StrategistOriginator(SO), selectedCollateral ); vm.startPrank(refinancer.addr); @@ -222,12 +228,12 @@ contract TestNewLoan is StarPortTest { ); debt.push(SpentItem({itemType: ItemType.ERC20, token: address(erc20s[0]), amount: 100, identifier: 0})); - Originator.Details memory loanDetails = Originator.Details({ + StrategistOriginator.Details memory loanDetails = StrategistOriginator.Details({ conduit: address(lenderConduit), custodian: address(custody), issuer: lender.addr, deadline: block.timestamp + 100, - offer: Originator.Offer({ + offer: StrategistOriginator.Offer({ salt: bytes32(0), terms: terms, collateral: ConsiderationItemLib.toSpentItemArray(selectedCollateral), @@ -246,7 +252,7 @@ contract TestNewLoan is StarPortTest { buyNowPayLater( advThingToSell, NewLoanData(address(custody), caveats, abi.encode(loanDetails)), - Originator(UO), + StrategistOriginator(SO), selectedCollateral ); } diff --git a/test/integration-testing/TestRepayLoan.sol b/test/integration-testing/TestRepayLoan.sol index 4e4f81bf..069b56dd 100644 --- a/test/integration-testing/TestRepayLoan.sol +++ b/test/integration-testing/TestRepayLoan.sol @@ -32,12 +32,12 @@ contract TestRepayLoan is StarPortTest { }) ); - Originator.Details memory loanDetails = Originator.Details({ + StrategistOriginator.Details memory loanDetails = StrategistOriginator.Details({ conduit: address(lenderConduit), custodian: address(custodian), issuer: lender.addr, deadline: block.timestamp + 100, - offer: Originator.Offer({ + offer: StrategistOriginator.Offer({ salt: bytes32(0), terms: terms, collateral: ConsiderationItemLib.toSpentItemArray(selectedCollateral), @@ -47,7 +47,7 @@ contract TestRepayLoan is StarPortTest { LoanManager.Loan memory activeLoan = newLoan( NewLoanData(address(custodian), new LoanManager.Caveat[](0), abi.encode(loanDetails)), - Originator(UO), + StrategistOriginator(SO), selectedCollateral ); vm.startPrank(borrower.addr); diff --git a/test/unit-testing/TestCustodian.sol b/test/unit-testing/TestCustodian.sol index cd427e8d..82d1697d 100644 --- a/test/unit-testing/TestCustodian.sol +++ b/test/unit-testing/TestCustodian.sol @@ -33,13 +33,13 @@ contract TestCustodian is StarPortTest, DeepEq, MockCall { erc20s[0].approve(address(lenderConduit), 100000); - Originator.Details memory loanDetails = _generateOriginationDetails( + StrategistOriginator.Details memory loanDetails = _generateOriginationDetails( _getERC721Consideration(erc721s[0]), _getERC20SpentItem(erc20s[0], borrowAmount), lender.addr ); LoanManager.Loan memory loan = newLoan( NewLoanData(address(custodian), new LoanManager.Caveat[](0), abi.encode(loanDetails)), - Originator(UO), + StrategistOriginator(SO), selectedCollateral ); Custodian(custodian).mint(loan); @@ -260,13 +260,13 @@ contract TestCustodian is StarPortTest, DeepEq, MockCall { function testGenerateOrderRepayERC1155WithRevert() public { //1155 - Originator.Details memory loanDetails = _generateOriginationDetails( + StrategistOriginator.Details memory loanDetails = _generateOriginationDetails( _getERC1155Consideration(erc1155s[0]), _getERC20SpentItem(erc20s[0], borrowAmount), address(issuer) ); LoanManager.Loan memory loan = newLoan( NewLoanData(address(custodian), new LoanManager.Caveat[](0), abi.encode(loanDetails)), - Originator(UO), + StrategistOriginator(SO), selectedCollateral ); @@ -283,13 +283,13 @@ contract TestCustodian is StarPortTest, DeepEq, MockCall { function testGenerateOrderRepayERC1155AndERC20AndNativeHandlerAuthorized() public { //1155 - Originator.Details memory loanDetails = _generateOriginationDetails( + StrategistOriginator.Details memory loanDetails = _generateOriginationDetails( _getERC1155Consideration(erc1155s[0]), _getERC20SpentItem(erc20s[0], borrowAmount), address(issuer) ); LoanManager.Loan memory loan = newLoan( NewLoanData(address(custodian), new LoanManager.Caveat[](0), abi.encode(loanDetails)), - Originator(UO), + StrategistOriginator(SO), selectedCollateral ); @@ -307,7 +307,7 @@ contract TestCustodian is StarPortTest, DeepEq, MockCall { loan = newLoan( NewLoanData(address(custodian), new LoanManager.Caveat[](0), abi.encode(loanDetails)), - Originator(UO), + StrategistOriginator(SO), selectedCollateral ); @@ -323,7 +323,7 @@ contract TestCustodian is StarPortTest, DeepEq, MockCall { loan = newLoan( NewLoanData(address(custodian), new LoanManager.Caveat[](0), abi.encode(loanDetails)), - Originator(UO), + StrategistOriginator(SO), selectedCollateral ); @@ -335,13 +335,13 @@ contract TestCustodian is StarPortTest, DeepEq, MockCall { function testGenerateOrderRepayERC1155AndERC20AndNative() public { //1155 - Originator.Details memory loanDetails = _generateOriginationDetails( + StrategistOriginator.Details memory loanDetails = _generateOriginationDetails( _getERC1155Consideration(erc1155s[0]), _getERC20SpentItem(erc20s[0], borrowAmount), address(issuer) ); LoanManager.Loan memory loan = newLoan( NewLoanData(address(custodian), new LoanManager.Caveat[](0), abi.encode(loanDetails)), - Originator(UO), + StrategistOriginator(SO), selectedCollateral ); @@ -356,7 +356,7 @@ contract TestCustodian is StarPortTest, DeepEq, MockCall { loan = newLoan( NewLoanData(address(custodian), new LoanManager.Caveat[](0), abi.encode(loanDetails)), - Originator(UO), + StrategistOriginator(SO), selectedCollateral ); @@ -371,7 +371,7 @@ contract TestCustodian is StarPortTest, DeepEq, MockCall { loan = newLoan( NewLoanData(address(custodian), new LoanManager.Caveat[](0), abi.encode(loanDetails)), - Originator(UO), + StrategistOriginator(SO), selectedCollateral ); diff --git a/test/unit-testing/TestLoanManager.sol b/test/unit-testing/TestLoanManager.sol index a87b6478..d7568166 100644 --- a/test/unit-testing/TestLoanManager.sol +++ b/test/unit-testing/TestLoanManager.sol @@ -1,8 +1,10 @@ import "starport-test/StarPortTest.sol"; import {StarPortLib} from "starport-core/lib/StarPortLib.sol"; -contract MockOriginator is Originator, TokenReceiverInterface { - constructor(LoanManager LM_, address strategist_, uint256 fee_) Originator(LM_, strategist_, fee_, msg.sender) {} +contract MockOriginator is StrategistOriginator, TokenReceiverInterface { + constructor(LoanManager LM_, address strategist_, uint256 fee_) + StrategistOriginator(LM_, strategist_, fee_, msg.sender) + {} // PUBLIC FUNCTIONS function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) @@ -32,7 +34,7 @@ contract MockOriginator is Originator, TokenReceiverInterface { return TokenReceiverInterface.onERC1155BatchReceived.selector; } - function terms(bytes calldata) public view override returns (LoanManager.Terms memory) { + function terms(bytes calldata) public view returns (LoanManager.Terms memory) { return LoanManager.Terms({ hook: address(0), handler: address(0), @@ -80,7 +82,7 @@ contract TestLoanManager is StarPortTest { } function testGenerateOrder() public { - Originator originator = new MockOriginator(LM, address(0), 0); + StrategistOriginator originator = new MockOriginator(LM, address(0), 0); address seaport = address(LM.seaport()); debt.push(SpentItem({itemType: ItemType.ERC20, token: address(erc20s[0]), amount: 100, identifier: 0}));