-
Notifications
You must be signed in to change notification settings - Fork 9
Feat: Origination Controller STIRFRY (Set Term Interest Rate Fixed Rate Yield) #134
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
base: main
Are you sure you want to change the base?
Changes from 11 commits
9346b40
b159706
cd54e09
f9c6a27
ea1a329
2161a9a
5edc659
113cce8
dba7599
3b6b8bd
34b374e
f528119
c35874b
946d614
3f8d88f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -276,6 +276,67 @@ error OCM_CollateralMismatch( | |
| */ | ||
| error OCM_LenderIsBorrower(); | ||
|
|
||
| // =============================== ORIGINATION CONTROLLER STIRFRY ================================ | ||
| /// @notice All errors prefixed with OCS_, to separate from other contracts in the protocol. | ||
|
|
||
| /** | ||
| * @notice Zero address passed in where not allowed. | ||
| * | ||
| * @param addressType The name of the parameter for which a zero address was provided. | ||
| */ | ||
| error OCS_ZeroAddress(string addressType); | ||
|
|
||
| /** | ||
| * @notice The loan terms payable currency and vaulted currency are not whitelisted as a valid pair | ||
| * for stirfry loans. | ||
| * | ||
| * @param payableCurrency The currency of the loan terms. | ||
| * @param vaultedCurrency The currency of the vaulted collateral. | ||
| */ | ||
| error OCS_InvalidStirfryPair(address payableCurrency, address vaultedCurrency); | ||
|
|
||
| /** | ||
| * @notice The loan terms principal multiplied by the payableToVaultedCurrencyRatio does not | ||
| * equal the vaulted collateral amount. | ||
| * | ||
| * @param principal The principal amount in the loan terms. | ||
| * @param payableToVaultedCurrencyRatio The 1 to 1 ratio of the vaulted collateral amount to the | ||
| * loan terms payable currency amount. | ||
| * @param lenderVaultedCurrencyAmount The amount of vaulted collateral. | ||
| */ | ||
| error OCS_InvalidPrincipalAmounts( | ||
| uint256 principal, | ||
| uint256 payableToVaultedCurrencyRatio, | ||
| uint256 lenderVaultedCurrencyAmount | ||
| ); | ||
|
|
||
| /** | ||
| * @notice The vaulted currency amount specified is not equivalent to what is actually vaulted. | ||
| * | ||
| * @param actualVaultedCollateralAmount The actual balance of collateral ERC20 in the vault. | ||
| * @param proviededVaultedCurrencyAmount The provided input for loan origination. | ||
| */ | ||
| error OCS_InvalidVaultAmount( | ||
| uint256 actualVaultedCollateralAmount, | ||
| uint256 proviededVaultedCurrencyAmount | ||
|
||
| ); | ||
|
|
||
| /** | ||
| * @notice The total interest due over the duration of the loan terms multiplied by the | ||
| * payableToVaultedCurrencyRatio does not equal the vaulted fixed interest amount | ||
| * provided by the borrower. | ||
| * | ||
| * @param totalInterest The total interest due. | ||
| * @param payableToVaultedCurrencyRatio The 1 to 1 ratio of the vaulted collateral amount to the | ||
| * loan terms payable currency amount. | ||
| * @param borrowerVaultedCurrencyAmount The fixed interest amount provided by the borrower. | ||
| */ | ||
| error OCS_InvalidInterestAmounts( | ||
| uint256 totalInterest, | ||
| uint256 payableToVaultedCurrencyRatio, | ||
| uint256 borrowerVaultedCurrencyAmount | ||
| ); | ||
|
|
||
| // ================================== CROSS CURRENCY ROLLOVER ==================================== | ||
| /// @notice All errors prefixed with CCR_, to separate from other contracts in the protocol. | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| pragma solidity 0.8.18; | ||
|
|
||
| import "./IOriginationControllerBase.sol"; | ||
|
|
||
| import "../libraries/LoanLibrary.sol"; | ||
|
|
||
| interface IOriginationControllerSTIRFRY is IOriginationControllerBase { | ||
|
||
|
|
||
| // ============= Data Types ============= | ||
|
|
||
| struct StirfryData { | ||
| address vaultedCurrency; | ||
| uint256 lenderVaultedCurrencyAmount; | ||
| uint256 borrowerVaultedCurrencyAmount; | ||
| uint256 payableToVaultedCurrencyRatio; | ||
|
||
| } | ||
|
|
||
| // ============= Loan Origination ============= | ||
|
|
||
| function initializeStirfryLoan( | ||
| LoanLibrary.LoanTerms calldata loanTerms, | ||
| StirfryData calldata stirfryData, | ||
| address borrower, | ||
| address lender, | ||
| Signature calldata sig, | ||
| SigProperties calldata sigProperties, | ||
| LoanLibrary.Predicate[] calldata itemPredicates | ||
|
||
| ) external returns (uint256 loanId); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,16 +9,14 @@ import "@openzeppelin/contracts/access/AccessControlEnumerable.sol"; | |
| import "./OriginationControllerBase.sol"; | ||
|
|
||
| import "../interfaces/IOriginationController.sol"; | ||
| import "../interfaces/IFeeController.sol"; | ||
| import "../interfaces/IExpressBorrow.sol"; | ||
|
|
||
| import "../libraries/FeeLookups.sol"; | ||
|
|
||
| import { OC_InvalidState } from "../errors/Lending.sol"; | ||
|
|
||
| import { | ||
| OC_ApprovedOwnLoan, | ||
| OC_InvalidSignature, | ||
| OC_CallerNotParticipant, | ||
| OC_SideMismatch, | ||
| OC_RolloverCurrencyMismatch, | ||
| OC_RolloverCollateralMismatch, | ||
| OC_ZeroAddress | ||
|
|
@@ -43,7 +41,12 @@ import { | |
| * does not move from escrow in LoanCore. Only the payable currency is transferred | ||
| * where applicable. | ||
| */ | ||
| contract OriginationController is IOriginationController, OriginationControllerBase, FeeLookups, AccessControlEnumerable, ReentrancyGuard { | ||
| contract OriginationController is | ||
| IOriginationController, | ||
| OriginationControllerBase, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can remove import |
||
| AccessControlEnumerable, | ||
| ReentrancyGuard | ||
| { | ||
| using SafeERC20 for IERC20; | ||
|
|
||
| // ============================================ STATE ============================================== | ||
|
|
@@ -316,44 +319,4 @@ contract OriginationController is IOriginationController, OriginationControllerB | |
| newTerms.collateralId | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * @dev Ensure that one counterparty has signed the loan terms, and the other | ||
| * has initiated the transaction. | ||
| * | ||
| * @param signingCounterparty The address of the counterparty who signed the terms. | ||
| * @param callingCounterparty The address on the other side of the loan as the signingCounterparty. | ||
| * @param caller The address initiating the transaction. | ||
| * @param signer The address recovered from the loan terms signature. | ||
| * @param sig A struct containing the signature data (for checking EIP-1271). | ||
| * @param sighash The hash of the signature payload (used for EIP-1271 check). | ||
| */ | ||
| // solhint-disable-next-line code-complexity | ||
| function _validateCounterparties( | ||
| address signingCounterparty, | ||
| address callingCounterparty, | ||
| address caller, | ||
| address signer, | ||
| Signature calldata sig, | ||
| bytes32 sighash | ||
| ) internal view { | ||
| // Make sure the signer recovered from the loan terms is not the caller, | ||
| // and even if the caller is approved, the caller is not the signing counterparty | ||
| if (caller == signer || caller == signingCounterparty) revert OC_ApprovedOwnLoan(caller); | ||
|
|
||
| // Check that caller can actually call this function - neededSide assignment | ||
| // defaults to BORROW if the signature is not approved by the borrower, but it could | ||
| // also not be a participant | ||
| if (!isSelfOrApproved(callingCounterparty, caller)) { | ||
| revert OC_CallerNotParticipant(msg.sender); | ||
| } | ||
|
|
||
| // Check signature validity | ||
| if (!isSelfOrApproved(signingCounterparty, signer) && !OriginationLibrary.isApprovedForContract(signingCounterparty, sig, sighash)) { | ||
| revert OC_InvalidSignature(signingCounterparty, signer); | ||
| } | ||
|
|
||
| // Revert if the signer is the calling counterparty | ||
| if (signer == callingCounterparty) revert OC_SideMismatch(signer); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,31 +7,30 @@ import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; | |
|
|
||
| import "./OriginationCalculator.sol"; | ||
|
|
||
| import "../interfaces/IOriginationController.sol"; | ||
| import "../interfaces/IOriginationHelpers.sol"; | ||
| import "../interfaces/ILoanCore.sol"; | ||
| import "../interfaces/IFeeController.sol"; | ||
| import "../interfaces/IExpressBorrow.sol"; | ||
|
|
||
| import "../libraries/OriginationLibrary.sol"; | ||
| import "../libraries/Constants.sol"; | ||
|
|
||
| import "../verifiers/ArcadeItemsVerifier.sol"; | ||
|
|
||
| import { OC_ZeroAddress, OC_SelfApprove } from "../errors/Lending.sol"; | ||
| import { | ||
| OC_ZeroAddress, | ||
| OC_SelfApprove, | ||
| OC_SideMismatch, | ||
| OC_ApprovedOwnLoan, | ||
| OC_CallerNotParticipant, | ||
| OC_InvalidSignature | ||
| } from "../errors/Lending.sol"; | ||
|
|
||
| /** | ||
| * @title OriginationControllerBase | ||
| * @author Non-Fungible Technologies, Inc. | ||
| * | ||
| * The Origination Controller Base contract provides common functionality for all | ||
| * origination controllers, including signature verification and access control. | ||
| * It establishes access roles and integrates permission management along with | ||
| * signature verification functions. | ||
| * | ||
| * origination controllers, including signature verification, shared reference | ||
| * contracts, approved third party originators, and rollover calculation helpers. | ||
| */ | ||
| abstract contract OriginationControllerBase is IOriginationControllerBase, EIP712, OriginationCalculator { | ||
| // ============================================ STATE ============================================== | ||
| // ============================================ STATE =============================================== | ||
| // =============== Contract References =============== | ||
|
|
||
| IOriginationHelpers public immutable originationHelpers; | ||
|
|
@@ -170,7 +169,7 @@ abstract contract OriginationControllerBase is IOriginationControllerBase, EIP71 | |
| signer = ECDSA.recover(sighash, sig.v, sig.r, sig.s); | ||
| } | ||
|
|
||
| // ============================================ HELPER ============================================== | ||
| // ============================================ HELPERS ============================================= | ||
|
|
||
| /** | ||
| * @notice Determine the sighash and external signer given the loan terms, signature, nonce, | ||
|
|
@@ -214,6 +213,44 @@ abstract contract OriginationControllerBase is IOriginationControllerBase, EIP71 | |
| ); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * @dev Ensure that one counterparty has signed the loan terms, and the other | ||
| * has initiated the transaction. | ||
| * | ||
| * @param signingCounterparty The address of the counterparty who signed the terms. | ||
| * @param callingCounterparty The address on the other side of the loan as the signingCounterparty. | ||
| * @param caller The address initiating the transaction. | ||
| * @param signer The address recovered from the loan terms signature. | ||
| * @param sig A struct containing the signature data (for checking EIP-1271). | ||
| * @param sighash The hash of the signature payload (used for EIP-1271 check). | ||
| */ | ||
| // solhint-disable-next-line code-complexity | ||
| function _validateCounterparties( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function can stay in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The reason for putting it in the OCBase contract is so there is not duplicate code across two different OriginationControllers. Additionally, the OCBase contract is home to |
||
| address signingCounterparty, | ||
| address callingCounterparty, | ||
| address caller, | ||
| address signer, | ||
| Signature calldata sig, | ||
| bytes32 sighash | ||
| ) internal view { | ||
| // Make sure the signer recovered from the loan terms is not the caller, | ||
| // and even if the caller is approved, the caller is not the signing counterparty | ||
| if (caller == signer || caller == signingCounterparty) revert OC_ApprovedOwnLoan(caller); | ||
|
|
||
| // Check that caller can actually call this function - neededSide assignment | ||
| // defaults to BORROW if the signature is not approved by the borrower, but it could | ||
| // also not be a participant | ||
| if (!isSelfOrApproved(callingCounterparty, caller)) { | ||
| revert OC_CallerNotParticipant(msg.sender); | ||
| } | ||
|
|
||
| // Check signature validity | ||
| if (!isSelfOrApproved(signingCounterparty, signer) && !OriginationLibrary.isApprovedForContract(signingCounterparty, sig, sighash)) { | ||
| revert OC_InvalidSignature(signingCounterparty, signer); | ||
| } | ||
|
|
||
| // Revert if the signer is the calling counterparty | ||
| if (signer == callingCounterparty) revert OC_SideMismatch(signer); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
proviededVaultedCurrencyAmounttypo inprovided.