Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 2,120 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Repay | 21245195 | 18 hrs ago | IN | 0 ETH | 0.00447526 | ||||
Repay | 21245180 | 18 hrs ago | IN | 0 ETH | 0.00410506 | ||||
Repay | 21245178 | 18 hrs ago | IN | 0 ETH | 0.0045878 | ||||
Repay | 21244855 | 19 hrs ago | IN | 0 ETH | 0.00422184 | ||||
Repay | 21244822 | 19 hrs ago | IN | 0 ETH | 0.00438599 | ||||
Repay | 21243857 | 22 hrs ago | IN | 0 ETH | 0.0047093 | ||||
Repay | 21242827 | 26 hrs ago | IN | 0 ETH | 0.00272576 | ||||
Repay | 21242672 | 26 hrs ago | IN | 0 ETH | 0.00330053 | ||||
Repay | 21241743 | 30 hrs ago | IN | 0 ETH | 0.00242532 | ||||
Repay | 21241701 | 30 hrs ago | IN | 0 ETH | 0.00197448 | ||||
Repay | 21241630 | 30 hrs ago | IN | 0 ETH | 0.00201665 | ||||
Claim | 21241624 | 30 hrs ago | IN | 0 ETH | 0.00155738 | ||||
Claim | 21241616 | 30 hrs ago | IN | 0 ETH | 0.00197363 | ||||
Claim | 21241616 | 30 hrs ago | IN | 0 ETH | 0.00199469 | ||||
Claim | 21241616 | 30 hrs ago | IN | 0 ETH | 0.00153705 | ||||
Repay | 21241569 | 30 hrs ago | IN | 0 ETH | 0.00197386 | ||||
Claim | 21240608 | 33 hrs ago | IN | 0 ETH | 0.00207939 | ||||
Repay | 21240402 | 34 hrs ago | IN | 0 ETH | 0.00327155 | ||||
Repay | 21237366 | 44 hrs ago | IN | 0 ETH | 0.00517032 | ||||
Repay | 21236966 | 46 hrs ago | IN | 0 ETH | 0.00613548 | ||||
Repay | 21236652 | 47 hrs ago | IN | 0 ETH | 0.00861439 | ||||
Repay | 21236570 | 47 hrs ago | IN | 0 ETH | 0.01007014 | ||||
Repay | 21232465 | 2 days ago | IN | 0 ETH | 0.00266093 | ||||
Repay | 21231500 | 2 days ago | IN | 0 ETH | 0.00593806 | ||||
Repay | 21229499 | 2 days ago | IN | 0 ETH | 0.00513287 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
RepaymentController
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "./interfaces/IRepaymentController.sol"; import "./interfaces/IPromissoryNote.sol"; import "./interfaces/ILoanCore.sol"; import "./interfaces/IFeeController.sol"; import "./libraries/InterestCalculator.sol"; import "./libraries/FeeLookups.sol"; import "./libraries/LoanLibrary.sol"; import { RC_ZeroAddress, RC_CannotDereference, RC_InvalidState, RC_OnlyLender } from "./errors/Lending.sol"; /** * @title RepaymentController * @author Non-Fungible Technologies, Inc. * * The Repayment Controller is the entry point for all loan lifecycle * operations in the Arcade.xyz lending protocol once a loan has begun. * This contract allows a caller to calculate an amount due on a loan, * repay an open loan, and claim collateral on a defaulted loan. It * is this contract's responsibility to verify loan conditions before * calling LoanCore. */ contract RepaymentController is IRepaymentController, InterestCalculator, FeeLookups { using SafeERC20 for IERC20; // ============================================ STATE =============================================== ILoanCore private immutable loanCore; IPromissoryNote private immutable lenderNote; IFeeController private immutable feeController; // ========================================= CONSTRUCTOR ============================================ /** * @notice Creates a new repayment controller contract. * * @dev For this controller to work, it needs to be granted the REPAYER_ROLE * in loan core after deployment. * * @param _loanCore The address of the loan core logic of the protocol. * @param _feeController The address of the fee logic of the protocol. */ constructor(address _loanCore, address _feeController) { if (_loanCore == address(0)) revert RC_ZeroAddress("loanCore"); if (_feeController == address(0)) revert RC_ZeroAddress("feeController"); loanCore = ILoanCore(_loanCore); lenderNote = loanCore.lenderNote(); feeController = IFeeController(_feeController); } // ==================================== LIFECYCLE OPERATIONS ======================================== /** * @notice Repay an active loan, referenced by borrower note ID (equivalent to loan ID). The interest for a loan * is calculated, and the principal plus interest is withdrawn from the caller. * Anyone can repay a loan. Control is passed to LoanCore to complete repayment. * * @param loanId The ID of the loan. */ function repay(uint256 loanId) external override { (uint256 amountFromBorrower, uint256 amountToLender) = _prepareRepay(loanId); // call repay function in loan core - msg.sender will pay the amountFromBorrower loanCore.repay(loanId, msg.sender, amountFromBorrower, amountToLender); } /** * @notice Repay an active loan, referenced by borrower note ID (equivalent to loan ID). The interest for a loan * is calculated, and the principal plus interest is withdrawn from the caller. Anyone can repay a loan. * Using forceRepay will not send funds to the lender: instead, those funds will be made * available for withdrawal in LoanCore. Can be used in cases where a borrower has funds to repay * but the lender is not able to receive those tokens (e.g. token blacklist). * * @param loanId The ID of the loan. */ function forceRepay(uint256 loanId) external override { (uint256 amountFromBorrower, uint256 amountToLender) = _prepareRepay(loanId); // call repay function in loan core - msg.sender will pay the amountFromBorrower loanCore.forceRepay(loanId, msg.sender, amountFromBorrower, amountToLender); } /** * @notice Claim collateral on an active loan, referenced by lender note ID (equivalent to loan ID). * The loan must be past the due date. No funds are collected * from the borrower. * * @param loanId The ID of the loan. */ function claim(uint256 loanId) external override { LoanLibrary.LoanData memory data = loanCore.getLoan(loanId); if (data.state == LoanLibrary.LoanState.DUMMY_DO_NOT_USE) revert RC_CannotDereference(loanId); // make sure that caller owns lender note // Implicitly checks if loan is active - if inactive, note will not exist address lender = lenderNote.ownerOf(loanId); if (lender != msg.sender) revert RC_OnlyLender(lender, msg.sender); LoanLibrary.LoanTerms memory terms = data.terms; uint256 interest = getInterestAmount(terms.principal, terms.proratedInterestRate); uint256 totalOwed = terms.principal + interest; uint256 claimFee = (totalOwed * data.feeSnapshot.lenderDefaultFee) / BASIS_POINTS_DENOMINATOR; loanCore.claim(loanId, claimFee); } /** * @notice Redeem a lender note for a completed return in return for funds repaid in an earlier * transaction via forceRepay. The lender note must be owned by the caller. * * @param loanId The ID of the lender note to redeem. */ function redeemNote(uint256 loanId, address to) external override { if (to == address(0)) revert RC_ZeroAddress("to"); LoanLibrary.LoanData memory data = loanCore.getLoan(loanId); (, uint256 amountOwed) = loanCore.getNoteReceipt(loanId); if (data.state != LoanLibrary.LoanState.Repaid) revert RC_InvalidState(data.state); address lender = lenderNote.ownerOf(loanId); if (lender != msg.sender) revert RC_OnlyLender(lender, msg.sender); uint256 redeemFee = (amountOwed * feeController.getLendingFee(FL_08)) / BASIS_POINTS_DENOMINATOR; loanCore.redeemNote(loanId, redeemFee, to); } // =========================================== HELPERS ============================================== /** * @dev Shared logic to perform validation and calculations for repay and forceRepay. * * @param loanId The ID of the loan. * * @return amountFromBorrower The amount to collect from the borrower. * @return amountToLender The amount owed to the lender. */ function _prepareRepay(uint256 loanId) internal view returns (uint256 amountFromBorrower, uint256 amountToLender) { LoanLibrary.LoanData memory data = loanCore.getLoan(loanId); if (data.state == LoanLibrary.LoanState.DUMMY_DO_NOT_USE) revert RC_CannotDereference(loanId); if (data.state != LoanLibrary.LoanState.Active) revert RC_InvalidState(data.state); LoanLibrary.LoanTerms memory terms = data.terms; uint256 interest = getInterestAmount(terms.principal, terms.proratedInterestRate); uint256 interestFee = (interest * data.feeSnapshot.lenderInterestFee) / BASIS_POINTS_DENOMINATOR; uint256 principalFee = (terms.principal * data.feeSnapshot.lenderPrincipalFee) / BASIS_POINTS_DENOMINATOR; amountFromBorrower = terms.principal + interest; amountToLender = amountFromBorrower - interestFee - principalFee; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; interface IRepaymentController { // ============== Lifeycle Operations ============== function repay(uint256 loanId) external; function forceRepay(uint256 loanId) external; function claim(uint256 loanId) external; function redeemNote(uint256 loanId, address to) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol"; import "./INFTWithDescriptor.sol"; interface IPromissoryNote is INFTWithDescriptor, IERC721Enumerable { // ============== Token Operations ============== function mint(address to, uint256 loanId) external returns (uint256); function burn(uint256 tokenId) external; // ============== Initializer ============== function initialize(address loanCore) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; import "../libraries/LoanLibrary.sol"; import "./IPromissoryNote.sol"; interface ILoanCore { // ================ Data Types ================= struct AffiliateSplit { address affiliate; uint96 splitBps; } struct NoteReceipt { address token; uint256 amount; } // ================ Events ================= event LoanStarted(uint256 loanId, address lender, address borrower); event LoanRepaid(uint256 loanId); event ForceRepay(uint256 loanId); event LoanRolledOver(uint256 oldLoanId, uint256 newLoanId); event LoanClaimed(uint256 loanId); event NoteRedeemed(address indexed token, address indexed caller, address indexed to, uint256 tokenId, uint256 amount); event NonceUsed(address indexed user, uint160 nonce); event FeesWithdrawn(address indexed token, address indexed caller, address indexed to, uint256 amount); event AffiliateSet(bytes32 indexed code, address indexed affiliate, uint96 splitBps); // ============== Lifecycle Operations ============== function startLoan( address lender, address borrower, LoanLibrary.LoanTerms calldata terms, uint256 _amountFromLender, uint256 _amountToBorrower, LoanLibrary.FeeSnapshot calldata feeSnapshot ) external returns (uint256 loanId); function repay( uint256 loanId, address payer, uint256 _amountFromPayer, uint256 _amountToLender ) external; function forceRepay( uint256 loanId, address payer, uint256 _amountFromPayer, uint256 _amountToLender ) external; function claim( uint256 loanId, uint256 _amountFromLender ) external; function redeemNote( uint256 loanId, uint256 _amountFromLender, address to ) external; function rollover( uint256 oldLoanId, address borrower, address lender, LoanLibrary.LoanTerms calldata terms, uint256 _settledAmount, uint256 _amountToOldLender, uint256 _amountToLender, uint256 _amountToBorrower ) external returns (uint256 newLoanId); // ============== Nonce Management ============== function consumeNonce(address user, uint160 nonce) external; function cancelNonce(uint160 nonce) external; // ============== Fee Management ============== function withdraw(address token, uint256 amount, address to) external; function withdrawProtocolFees(address token, address to) external; // ============== Admin Operations ============== function setAffiliateSplits(bytes32[] calldata codes, AffiliateSplit[] calldata splits) external; // ============== View Functions ============== function getLoan(uint256 loanId) external view returns (LoanLibrary.LoanData calldata loanData); function getNoteReceipt(uint256 loanId) external view returns (address token, uint256 amount); function isNonceUsed(address user, uint160 nonce) external view returns (bool); function borrowerNote() external view returns (IPromissoryNote); function lenderNote() external view returns (IPromissoryNote); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; interface IFeeController { // ================ Structs ================ struct FeesOrigination { uint16 borrowerOriginationFee; uint16 lenderOriginationFee; uint16 lenderDefaultFee; uint16 lenderInterestFee; uint16 lenderPrincipalFee; } struct FeesRollover { uint16 borrowerRolloverFee; uint16 lenderRolloverFee; } // ================ Events ================= event SetLendingFee(bytes32 indexed id, uint16 fee); event SetVaultMintFee(uint64 fee); // ================ Getter/Setter ================= function setLendingFee(bytes32 id, uint16 fee) external; function setVaultMintFee(uint64 fee) external; function getLendingFee(bytes32 id) external view returns (uint16); function getVaultMintFee() external view returns (uint64); function getFeesOrigination() external view returns (FeesOrigination memory); function getFeesRollover() external view returns (FeesRollover memory); function getMaxLendingFee(bytes32 id) external view returns (uint16); function getMaxVaultMintFee() external view returns (uint64); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; /** * @title InterestCalculator * @author Non-Fungible Technologies, Inc. * * Interface for calculating the interest amount * given an interest rate and principal amount. Assumes * that the interestRate is already expressed over the desired * time period. */ abstract contract InterestCalculator { // ============================================ STATE ============================================== /// @dev The units of precision equal to the minimum interest of 1 basis point. uint256 public constant INTEREST_RATE_DENOMINATOR = 1e18; uint256 public constant BASIS_POINTS_DENOMINATOR = 1e4; // ======================================== CALCULATIONS =========================================== /** * @notice Calculate the interest due over a full term. * * @dev Interest and principal must be entered with 18 units of * precision from the basis point unit (e.g. 1e18 == 0.01%) * * @param principal Principal amount in the loan terms. * @param proratedInterestRate Interest rate in the loan terms, prorated over loan duration. * * @return interest The amount of interest due. */ function getInterestAmount(uint256 principal, uint256 proratedInterestRate) public pure returns (uint256) { return principal * proratedInterestRate / (INTEREST_RATE_DENOMINATOR * BASIS_POINTS_DENOMINATOR); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; /** * @title FeeLookups * @author Non-Fungible Technologies, Inc. * * Enumerates unique identifiers for fee identifiers * that the lending protocol uses. */ abstract contract FeeLookups { /// @dev Origination fees: amount in bps, payable in loan token bytes32 public constant FL_01 = keccak256("BORROWER_ORIGINATION_FEE"); bytes32 public constant FL_02 = keccak256("LENDER_ORIGINATION_FEE"); /// @dev Rollover fees: amount in bps, payable in loan token bytes32 public constant FL_03 = keccak256("BORROWER_ROLLOVER_FEE"); bytes32 public constant FL_04 = keccak256("LENDER_ROLLOVER_FEE"); /// @dev Loan closure fees: amount in bps, payable in loan token bytes32 public constant FL_05 = keccak256("LENDER_DEFAULT_FEE"); bytes32 public constant FL_06 = keccak256("LENDER_INTEREST_FEE"); bytes32 public constant FL_07 = keccak256("LENDER_PRINCIPAL_FEE"); bytes32 public constant FL_08 = keccak256("LENDER_REDEEM_FEE"); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; /** * @title LoanLibrary * @author Non-Fungible Technologies, Inc. * * Contains all data types used across Arcade lending contracts. */ library LoanLibrary { /** * @dev Enum describing the current state of a loan. * State change flow: * Created -> Active -> Repaid * -> Defaulted */ enum LoanState { // We need a default that is not 'Created' - this is the zero value DUMMY_DO_NOT_USE, // The loan has been initialized, funds have been delivered to the borrower and the collateral is held. Active, // The loan has been repaid, and the collateral has been returned to the borrower. This is a terminal state. Repaid, // The loan was delinquent and collateral claimed by the lender. This is a terminal state. Defaulted } /** * @dev The raw terms of a loan. */ struct LoanTerms { // Interest expressed as a rate, unlike V1 gross value. // Input conversion: 0.01% = (1 * 10**18) , 10.00% = (1000 * 10**18) // This represents the rate over the lifetime of the loan, not APR. // 0.01% is the minimum interest rate allowed by the protocol. uint256 proratedInterestRate; /// @dev Full-slot variables // The amount of principal in terms of the payableCurrency. uint256 principal; // The token ID of the address holding the collateral. /// @dev Can be an AssetVault, or the NFT contract for unbundled collateral address collateralAddress; /// @dev Packed variables // The number of seconds representing relative due date of the loan. /// @dev Max is 94,608,000, fits in 96 bits uint96 durationSecs; // The token ID of the collateral. uint256 collateralId; // The payable currency for the loan principal and interest. address payableCurrency; // Timestamp for when signature for terms expires uint96 deadline; // Affiliate code used to start the loan. bytes32 affiliateCode; } /** * @dev Modification of loan terms, used for signing only. * Instead of a collateralId, a list of predicates * is defined by 'bytes' in items. */ struct LoanTermsWithItems { // Interest expressed as a rate, unlike V1 gross value. // Input conversion: 0.01% = (1 * 10**18) , 10.00% = (1000 * 10**18) // This represents the rate over the lifetime of the loan, not APR. // 0.01% is the minimum interest rate allowed by the protocol. uint256 proratedInterestRate; /// @dev Full-slot variables // The amount of principal in terms of the payableCurrency. uint256 principal; // The tokenID of the address holding the collateral address collateralAddress; /// @dev Packed variables // The number of seconds representing relative due date of the loan. /// @dev Max is 94,608,000, fits in 96 bits uint96 durationSecs; // An encoded list of predicates, along with their verifiers. bytes items; // The payable currency for the loan principal and interest. address payableCurrency; // Timestamp for when signature for terms expires uint96 deadline; // Affiliate code used to start the loan. bytes32 affiliateCode; } /** * @dev Predicate for item-based verifications */ struct Predicate { // The encoded predicate, to decoded and parsed by the verifier contract. bytes data; // The verifier contract. address verifier; } /** * @dev Snapshot of lending fees at the time of loan creation. */ struct FeeSnapshot { // The fee taken when lender claims defaulted collateral. uint16 lenderDefaultFee; // The fee taken from the borrower's interest repayment. uint16 lenderInterestFee; // The fee taken from the borrower's principal repayment. uint16 lenderPrincipalFee; } /** * @dev The data of a loan. This is stored once the loan is Active */ struct LoanData { /// @dev Packed variables // The current state of the loan. LoanState state; // Start date of the loan, using block.timestamp. uint160 startDate; /// @dev Full-slot variables // The raw terms of the loan. LoanTerms terms; // Record of lending fees at the time of loan creation. FeeSnapshot feeSnapshot; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; import "../libraries/LoanLibrary.sol"; /** * @title LendingErrors * @author Non-Fungible Technologies, Inc. * * This file contains custom errors for the core lending protocol contracts, with errors * prefixed by the contract that throws them (e.g., "OC_" for OriginationController). * Errors located in one place to make it possible to holistically look at all * protocol failure cases. */ // ==================================== ORIGINATION CONTROLLER ====================================== /// @notice All errors prefixed with OC_, 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 OC_ZeroAddress(string addressType); /** * @notice Ensure valid loan state for loan lifceycle operations. * * @param state Current state of a loan according to LoanState enum. */ error OC_InvalidState(LoanLibrary.LoanState state); /** * @notice Loan duration must be greater than 1hr and less than 3yrs. * * @param durationSecs Total amount of time in seconds. */ error OC_LoanDuration(uint256 durationSecs); /** * @notice Interest must be greater than 0.01% and less than 10,000%. (interestRate / 1e18 >= 1) * * @param interestRate InterestRate with 1e18 multiplier. */ error OC_InterestRate(uint256 interestRate); /** * @notice One of the predicates for item verification failed. * * @param borrower The address of the borrower. * @param lender The address of the lender. * @param verifier The address of the verifier contract. * @param collateralAddress The address of the collateral token. * @param collateralId The token ID of the collateral. * @param data The verification data (to be parsed by verifier). */ error OC_PredicateFailed( address borrower, address lender, address verifier, address collateralAddress, uint256 collateralId, bytes data ); /** * @notice The predicates array is empty. */ error OC_PredicatesArrayEmpty(); /** * @notice A caller attempted to approve themselves. * * @param caller The caller of the approve function. */ error OC_SelfApprove(address caller); /** * @notice A caller attempted to originate a loan with their own signature. * * @param caller The caller of the approve function, who was also the signer. */ error OC_ApprovedOwnLoan(address caller); /** * @notice The signature could not be recovered to the counterparty or approved party. * * @param target The target party of the signature, which should either be the signer, * or someone who has approved the signer. * @param signer The signer determined from ECDSA.recover. */ error OC_InvalidSignature(address target, address signer); /** * @notice The verifier contract specified in a predicate has not been whitelisted. * * @param verifier The verifier the caller attempted to use. */ error OC_InvalidVerifier(address verifier); /** * @notice The function caller was neither borrower or lender, and was not approved by either. * * @param caller The unapproved function caller. */ error OC_CallerNotParticipant(address caller); /** * @notice Signer is attempting to take the wrong side of the loan. * * @param signer The address of the external signer. */ error OC_SideMismatch(address signer); /** * @notice Two related parameters for batch operations did not match in length. */ error OC_BatchLengthMismatch(); /** * @notice Principal must be greater than 9999 Wei. * * @param principal Principal in ether. */ error OC_PrincipalTooLow(uint256 principal); /** * @notice Signature must not be expired. * * @param deadline Deadline in seconds. */ error OC_SignatureIsExpired(uint256 deadline); /** * @notice New currency does not match for a loan rollover request. * * @param oldCurrency The currency of the active loan. * @param newCurrency The currency of the new loan. */ error OC_RolloverCurrencyMismatch(address oldCurrency, address newCurrency); /** * @notice New currency does not match for a loan rollover request. * * @param oldCollateralAddress The address of the active loan's collateral. * @param newCollateralAddress The token ID of the active loan's collateral. * @param oldCollateralId The address of the new loan's collateral. * @param newCollateralId The token ID of the new loan's collateral. */ error OC_RolloverCollateralMismatch( address oldCollateralAddress, uint256 oldCollateralId, address newCollateralAddress, uint256 newCollateralId ); /** * @notice Provided payable currency address is not approved for lending. * * @param payableCurrency ERC20 token address supplied in loan terms. */ error OC_InvalidCurrency(address payableCurrency); /** * @notice Provided collateral address is not approved for lending. * * @param collateralAddress ERC721 or ERC1155 token address supplied in loan terms. */ error OC_InvalidCollateral(address collateralAddress); /** * @notice Provided token array does not hold any token addresses. */ error OC_ZeroArrayElements(); /** * @notice Provided token array holds more than 50 token addresses. */ error OC_ArrayTooManyElements(); // ==================================== ITEMS VERIFIER ====================================== /// @notice All errors prefixed with IV_, to separate from other contracts in the protocol. /** * @notice The predicate payload was decoded successfully, but list of predicates is empty. */ error IV_NoPredicates(); /** * @notice Provided SignatureItem is missing an address. */ error IV_ItemMissingAddress(); /** * @notice Provided SignatureItem has an invalid collateral type. * @dev Should never actually fire, since cType is defined by an enum, so will fail on decode. * * @param asset The NFT contract being checked. * @param cType The collateralTytpe provided. */ error IV_InvalidCollateralType(address asset, uint256 cType); /** * @notice Provided signature item with no required amount. For single ERC721s, specify 1. * * @param asset The NFT contract being checked. * @param amount The amount provided (should be 0). */ error IV_NoAmount(address asset, uint256 amount); /** * @notice Provided a wildcard for a non-ERC721. * * @param asset The NFT contract being checked. */ error IV_InvalidWildcard(address asset); /** * @notice The provided token ID is out of bounds for the given collection. * * @param tokenId The token ID provided. */ error IV_InvalidTokenId(int256 tokenId); /** * @notice The provided project ID does not exist on the target contract. Only * used for ArtBlocks. * * @param projectId The project ID provided. * @param nextProjectId The contract's reported nextProjectId. */ error IV_InvalidProjectId(uint256 projectId, uint256 nextProjectId); /** * @notice The provided collateralId converts to a vault, but * the vault's address does not convert back to the provided collateralId * when casted to a uint256. */ error IV_InvalidCollateralId(uint256 collateralId); // ==================================== REPAYMENT CONTROLLER ====================================== /// @notice All errors prefixed with RC_, 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 RC_ZeroAddress(string addressType); /** * @notice Could not dereference loan from loan ID. * * @param target The loanId being checked. */ error RC_CannotDereference(uint256 target); /** * @notice Ensure valid loan state for loan lifceycle operations. * * @param state Current state of a loan according to LoanState enum. */ error RC_InvalidState(LoanLibrary.LoanState state); /** * @notice Caller is not the owner of lender note. * * @param lender The owner of the lender note. * @param caller Msg.sender of the function call. */ error RC_OnlyLender(address lender, address caller); // ==================================== Loan Core ====================================== /// @notice All errors prefixed with LC_, 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 LC_ZeroAddress(string addressType); /// @notice Borrower address is same as lender address. error LC_ReusedNote(); /// @notice Zero amount passed in where not allowed. error LC_ZeroAmount(); /** * @notice Check collateral is not already used in a active loan. * * @param collateralAddress Address of the collateral. * @param collateralId ID of the collateral token. */ error LC_CollateralInUse(address collateralAddress, uint256 collateralId); /** * @notice The reported settlements are invalid, and LoanCore would lose tokens * attempting to perform the requested operations. * * * @param payout Amount of tokens to be paid out. * @param collected Amount of tokens to collect - should be fewer than payout. */ error LC_CannotSettle(uint256 payout, uint256 collected); /** * @notice User attempted to withdraw a pending balance that was in excess * of what is available. * * @param amount Amount of tokens to be withdrawn. * @param available Amount of tokens available to withdraw. */ error LC_CannotWithdraw(uint256 amount, uint256 available); /** * @notice Two arrays were provided that must be of matching length, but were not. * */ error LC_ArrayLengthMismatch(); /** * @notice A proposed affiliate split was submitted that is over the maximum. * * @param splitBps The proposed affiliate split. * @param maxSplitBps The maximum allowed affiliate split. * */ error LC_OverMaxSplit(uint96 splitBps, uint96 maxSplitBps); /** * @notice Ensure valid loan state for loan lifceycle operations. * * @param state Current state of a loan according to LoanState enum. */ error LC_InvalidState(LoanLibrary.LoanState state); /** * @notice Loan duration has not expired. * * @param dueDate Timestamp of the end of the loan duration. */ error LC_NotExpired(uint256 dueDate); /** * @notice User address and the specified nonce have already been used. * * @param user Address of collateral owner. * @param nonce Represents the number of transactions sent by address. */ error LC_NonceUsed(address user, uint160 nonce); /** * @notice Protocol attempted to set an affiliate code which already exists. Affiliate * codes are immutable. * * @param affiliateCode The affiliate code being set. */ error LC_AffiliateCodeAlreadySet(bytes32 affiliateCode); /** * @notice Specified note token ID does not have a redeemable receipt. * * @param loanId The loanId being checked. */ error LC_NoReceipt(uint256 loanId); /** * @notice Only Loan Core contract can call this function. */ error LC_CallerNotLoanCore(); /** * @notice The loan core contract has been irreversibly shut down. */ error LC_Shutdown(); // ==================================== Promissory Note ====================================== /// @notice All errors prefixed with PN_, 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 PN_ZeroAddress(string addressType); /** * @notice Caller of mint function must have the MINTER_ROLE in AccessControl. * * @param caller Address of the function caller. */ error PN_MintingRole(address caller); /** * @notice Caller of burn function must have the BURNER_ROLE in AccessControl. * * @param caller Address of the function caller. */ error PN_BurningRole(address caller); /** * @notice Non-existant token id provided as argument. * * @param tokenId The ID of the token to lookup the URI for. */ error PN_DoesNotExist(uint256 tokenId); // ==================================== Fee Controller ====================================== /// @notice All errors prefixed with FC_, to separate from other contracts in the protocol. /** * @notice Caller attempted to set a lending fee which is larger than the global maximum. */ error FC_LendingFeeOverMax(bytes32 selector, uint256 fee, uint256 maxFee); /** * @notice Caller attempted to set a vault mint fee which is larger than the global maximum. */ error FC_VaultMintFeeOverMax(uint256 fee, uint256 maxFee); // ==================================== ERC721 Permit ====================================== /// @notice All errors prefixed with ERC721P_, to separate from other contracts in the protocol. /** * @notice Deadline for the permit has expired. * * @param deadline Permit deadline parameter as a timestamp. */ error ERC721P_DeadlineExpired(uint256 deadline); /** * @notice Address of the owner to also be the owner of the tokenId. * * @param owner Owner parameter for the function call. */ error ERC721P_NotTokenOwner(address owner); /** * @notice Invalid signature. * * @param signer Signer recovered from ECDSA sugnature hash. */ error ERC721P_InvalidSignature(address signer);
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; interface INFTWithDescriptor { // ============= Events ============== event SetDescriptor(address indexed caller, address indexed descriptor); // ================ Resource Metadata ================ function tokenURI(uint256 tokenId) external view returns (string memory); function setDescriptor(address descriptor) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
{ "metadata": { "bytecodeHash": "none" }, "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_loanCore","type":"address"},{"internalType":"address","name":"_feeController","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"target","type":"uint256"}],"name":"RC_CannotDereference","type":"error"},{"inputs":[{"internalType":"enum LoanLibrary.LoanState","name":"state","type":"uint8"}],"name":"RC_InvalidState","type":"error"},{"inputs":[{"internalType":"address","name":"lender","type":"address"},{"internalType":"address","name":"caller","type":"address"}],"name":"RC_OnlyLender","type":"error"},{"inputs":[{"internalType":"string","name":"addressType","type":"string"}],"name":"RC_ZeroAddress","type":"error"},{"inputs":[],"name":"BASIS_POINTS_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FL_01","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FL_02","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FL_03","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FL_04","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FL_05","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FL_06","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FL_07","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FL_08","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INTEREST_RATE_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"loanId","type":"uint256"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"loanId","type":"uint256"}],"name":"forceRepay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"principal","type":"uint256"},{"internalType":"uint256","name":"proratedInterestRate","type":"uint256"}],"name":"getInterestAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"loanId","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"redeemNote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"loanId","type":"uint256"}],"name":"repay","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60e06040523480156200001157600080fd5b50604051620011cf380380620011cf83398101604081905262000034916200016b565b6001600160a01b0382166200007c5760405163302c848b60e01b81526020600482015260086024820152676c6f616e436f726560c01b60448201526064015b60405180910390fd5b6001600160a01b038116620000c55760405163302c848b60e01b815260206004820152600d60248201526c3332b2a1b7b73a3937b63632b960991b604482015260640162000073565b6001600160a01b038216608081905260408051600162010aa960e71b03198152905163ff7aab80916004808201926020929091908290030181865afa15801562000113573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001399190620001aa565b6001600160a01b0390811660a0521660c05250620001d1565b6001600160a01b03811681146200016857600080fd5b50565b600080604083850312156200017f57600080fd5b82516200018c8162000152565b60208401519092506200019f8162000152565b809150509250929050565b600060208284031215620001bd57600080fd5b8151620001ca8162000152565b9392505050565b60805160a05160c051610f9662000239600039600061091801526000818161044501526108250152600081816102f80152818161037b0152818161056901528181610611015281816106d001528181610768015281816109cb0152610a380152610f966000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c8063a7146e7111610097578063cfa498a311610066578063cfa498a31461023f578063db0a23c114610248578063ddb220ec1461026f578063ededcc411461029657600080fd5b8063a7146e71146101cf578063b8921e26146101f6578063c9498e541461021d578063cc3266e81461023057600080fd5b8063379607f5116100d3578063379607f51461016f57806359c86a11146101825780637eb094981461019557806384d2b81c146101bc57600080fd5b8063227e8f0c146100fa57806333f6b51c14610133578063371fd8e61461015a575b600080fd5b6101217f6b9fec8a90acd71b357b3fbde8e525c5e0a0ffebe7010905e79162a4fd6421bd81565b60405190815260200160405180910390f35b6101217fddfa60b1f3b0c3629357d48d7f8a1186bd1ff199faa6c6b792597e91bd705dc281565b61016d610168366004610bd7565b6102bd565b005b61016d61017d366004610bd7565b610362565b61016d610190366004610bd7565b6105d6565b6101217f4e2344e60c4b990f3c4cf2efa216c71144a011f9e4a940c6b459a8066c98e1f981565b6101216101ca366004610bf0565b610648565b6101217f41f539feb01b3a702d5e8c2e4367fa0d5a544df6b5ef24765c6836e0743db74281565b6101217f74ba47f4e32f0deada0ece4f758dd1cb5f98ba44c024c037a61f34bb066f568e81565b61016d61022b366004610c2a565b61067b565b610121670de0b6b3a764000081565b61012161271081565b6101217f6c9950464c33f914161b87af80469f5598c7ea5009d7b4464f7e3815112686a381565b6101217fc3a599955a4238a21ad67957aa12a28dc3e88efd2a54bc264ba15e23b257c35281565b6101217f4714fd9784ca8c9ee16df7000f2eb0fc7a2296e457de6968bc65d71fd287370681565b6000806102c983610a31565b6040516304f3841960e21b815260048101869052336024820152604481018390526064810182905291935091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906313ce1064906084015b600060405180830381600087803b15801561034557600080fd5b505af1158015610359573d6000803e3d6000fd5b50505050505050565b604051632820036560e11b8152600481018290526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063504006ca906024016101a060405180830381865afa1580156103cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ef9190610d7e565b905060008151600381111561040657610406610e69565b0361042c57604051630fd8a76760e01b8152600481018390526024015b60405180910390fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610494573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b89190610e7f565b90506001600160a01b03811633146104f457604051636b9e14ff60e01b81526001600160a01b0382166004820152336024820152604401610423565b60408201516020810151815160009161050c91610648565b905060008183602001516105209190610eb9565b9050600061271086606001516000015161ffff168361053f9190610ecc565b6105499190610ee3565b60405163c349026360e01b815260048101899052602481018290529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c349026390604401600060405180830381600087803b1580156105b557600080fd5b505af11580156105c9573d6000803e3d6000fd5b5050505050505050505050565b6000806105e283610a31565b60405163bb340b5d60e01b815260048101869052336024820152604481018390526064810182905291935091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063bb340b5d9060840161032b565b600061065e612710670de0b6b3a7640000610ecc565b6106688385610ecc565b6106729190610ee3565b90505b92915050565b6001600160a01b0381166106b75760405163302c848b60e01b8152602060048201526002602482015261746f60f01b6044820152606401610423565b604051632820036560e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063504006ca906024016101a060405180830381865afa158015610720573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107449190610d7e565b6040516385b2f18360e01b8152600481018590529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906385b2f183906024016040805180830381865afa1580156107ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d29190610f05565b915060029050825160038111156107eb576107eb610e69565b1461080c578151604051631b250a6b60e11b81526104239190600401610f33565b6040516331a9108f60e11b8152600481018590526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610874573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108989190610e7f565b90506001600160a01b03811633146108d457604051636b9e14ff60e01b81526001600160a01b0382166004820152336024820152604401610423565b60405163aee758e760e01b81527f4714fd9784ca8c9ee16df7000f2eb0fc7a2296e457de6968bc65d71fd28737066004820152600090612710906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063aee758e790602401602060405180830381865afa15801561095f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109839190610f5b565b6109919061ffff1685610ecc565b61099b9190610ee3565b60405163a443a63560e01b815260048101889052602481018290526001600160a01b0387811660448301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063a443a63590606401600060405180830381600087803b158015610a1157600080fd5b505af1158015610a25573d6000803e3d6000fd5b50505050505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663504006ca856040518263ffffffff1660e01b8152600401610a8491815260200190565b6101a060405180830381865afa158015610aa2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac69190610d7e565b9050600081516003811115610add57610add610e69565b03610afe57604051630fd8a76760e01b815260048101859052602401610423565b600181516003811115610b1357610b13610e69565b14610b34578051604051631b250a6b60e11b81526104239190600401610f33565b604081015160208101518151600091610b4c91610648565b9050600061271084606001516020015161ffff1683610b6b9190610ecc565b610b759190610ee3565b9050600061271085606001516040015161ffff168560200151610b989190610ecc565b610ba29190610ee3565b9050828460200151610bb49190610eb9565b965080610bc18389610f76565b610bcb9190610f76565b95505050505050915091565b600060208284031215610be957600080fd5b5035919050565b60008060408385031215610c0357600080fd5b50508035926020909101359150565b6001600160a01b0381168114610c2757600080fd5b50565b60008060408385031215610c3d57600080fd5b823591506020830135610c4f81610c12565b809150509250929050565b6040516080810167ffffffffffffffff81118282101715610c8b57634e487b7160e01b600052604160045260246000fd5b60405290565b604051610100810167ffffffffffffffff81118282101715610c8b57634e487b7160e01b600052604160045260246000fd5b8051610cce81610c12565b919050565b80516bffffffffffffffffffffffff81168114610cce57600080fd5b805161ffff81168114610cce57600080fd5b600060608284031215610d1357600080fd5b6040516060810181811067ffffffffffffffff82111715610d4457634e487b7160e01b600052604160045260246000fd5b604052905080610d5383610cef565b8152610d6160208401610cef565b6020820152610d7260408401610cef565b60408201525092915050565b60008183036101a0811215610d9257600080fd5b610d9a610c5a565b835160048110610da957600080fd5b81526020840151610db981610c12565b6020820152610100603f198301811315610dd257600080fd5b610dda610c91565b925060408501518352606085015160208401526080850151610dfb81610c12565b6040840152610e0c60a08601610cd3565b606084015260c08501516080840152610e2760e08601610cc3565b60a0840152610e37818601610cd3565b60c08401525061012084015160e0830152816040820152610e5c856101408601610d01565b6060820152949350505050565b634e487b7160e01b600052602160045260246000fd5b600060208284031215610e9157600080fd5b8151610e9c81610c12565b9392505050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561067557610675610ea3565b808202811582820484141761067557610675610ea3565b600082610f0057634e487b7160e01b600052601260045260246000fd5b500490565b60008060408385031215610f1857600080fd5b8251610f2381610c12565b6020939093015192949293505050565b6020810160048310610f5557634e487b7160e01b600052602160045260246000fd5b91905290565b600060208284031215610f6d57600080fd5b61067282610cef565b8181038181111561067557610675610ea356fea164736f6c6343000812000a00000000000000000000000089bc08ba00f135d608bc335f6b33d7a9abcc98af000000000000000000000000f764442856eb3fe68a0828e07246a4b395e800fa
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100f55760003560e01c8063a7146e7111610097578063cfa498a311610066578063cfa498a31461023f578063db0a23c114610248578063ddb220ec1461026f578063ededcc411461029657600080fd5b8063a7146e71146101cf578063b8921e26146101f6578063c9498e541461021d578063cc3266e81461023057600080fd5b8063379607f5116100d3578063379607f51461016f57806359c86a11146101825780637eb094981461019557806384d2b81c146101bc57600080fd5b8063227e8f0c146100fa57806333f6b51c14610133578063371fd8e61461015a575b600080fd5b6101217f6b9fec8a90acd71b357b3fbde8e525c5e0a0ffebe7010905e79162a4fd6421bd81565b60405190815260200160405180910390f35b6101217fddfa60b1f3b0c3629357d48d7f8a1186bd1ff199faa6c6b792597e91bd705dc281565b61016d610168366004610bd7565b6102bd565b005b61016d61017d366004610bd7565b610362565b61016d610190366004610bd7565b6105d6565b6101217f4e2344e60c4b990f3c4cf2efa216c71144a011f9e4a940c6b459a8066c98e1f981565b6101216101ca366004610bf0565b610648565b6101217f41f539feb01b3a702d5e8c2e4367fa0d5a544df6b5ef24765c6836e0743db74281565b6101217f74ba47f4e32f0deada0ece4f758dd1cb5f98ba44c024c037a61f34bb066f568e81565b61016d61022b366004610c2a565b61067b565b610121670de0b6b3a764000081565b61012161271081565b6101217f6c9950464c33f914161b87af80469f5598c7ea5009d7b4464f7e3815112686a381565b6101217fc3a599955a4238a21ad67957aa12a28dc3e88efd2a54bc264ba15e23b257c35281565b6101217f4714fd9784ca8c9ee16df7000f2eb0fc7a2296e457de6968bc65d71fd287370681565b6000806102c983610a31565b6040516304f3841960e21b815260048101869052336024820152604481018390526064810182905291935091507f00000000000000000000000089bc08ba00f135d608bc335f6b33d7a9abcc98af6001600160a01b0316906313ce1064906084015b600060405180830381600087803b15801561034557600080fd5b505af1158015610359573d6000803e3d6000fd5b50505050505050565b604051632820036560e11b8152600481018290526000907f00000000000000000000000089bc08ba00f135d608bc335f6b33d7a9abcc98af6001600160a01b03169063504006ca906024016101a060405180830381865afa1580156103cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ef9190610d7e565b905060008151600381111561040657610406610e69565b0361042c57604051630fd8a76760e01b8152600481018390526024015b60405180910390fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000092ed78b41537c902ad287608d8535bb6780a76186001600160a01b031690636352211e90602401602060405180830381865afa158015610494573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b89190610e7f565b90506001600160a01b03811633146104f457604051636b9e14ff60e01b81526001600160a01b0382166004820152336024820152604401610423565b60408201516020810151815160009161050c91610648565b905060008183602001516105209190610eb9565b9050600061271086606001516000015161ffff168361053f9190610ecc565b6105499190610ee3565b60405163c349026360e01b815260048101899052602481018290529091507f00000000000000000000000089bc08ba00f135d608bc335f6b33d7a9abcc98af6001600160a01b03169063c349026390604401600060405180830381600087803b1580156105b557600080fd5b505af11580156105c9573d6000803e3d6000fd5b5050505050505050505050565b6000806105e283610a31565b60405163bb340b5d60e01b815260048101869052336024820152604481018390526064810182905291935091507f00000000000000000000000089bc08ba00f135d608bc335f6b33d7a9abcc98af6001600160a01b03169063bb340b5d9060840161032b565b600061065e612710670de0b6b3a7640000610ecc565b6106688385610ecc565b6106729190610ee3565b90505b92915050565b6001600160a01b0381166106b75760405163302c848b60e01b8152602060048201526002602482015261746f60f01b6044820152606401610423565b604051632820036560e11b8152600481018390526000907f00000000000000000000000089bc08ba00f135d608bc335f6b33d7a9abcc98af6001600160a01b03169063504006ca906024016101a060405180830381865afa158015610720573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107449190610d7e565b6040516385b2f18360e01b8152600481018590529091506000906001600160a01b037f00000000000000000000000089bc08ba00f135d608bc335f6b33d7a9abcc98af16906385b2f183906024016040805180830381865afa1580156107ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d29190610f05565b915060029050825160038111156107eb576107eb610e69565b1461080c578151604051631b250a6b60e11b81526104239190600401610f33565b6040516331a9108f60e11b8152600481018590526000907f00000000000000000000000092ed78b41537c902ad287608d8535bb6780a76186001600160a01b031690636352211e90602401602060405180830381865afa158015610874573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108989190610e7f565b90506001600160a01b03811633146108d457604051636b9e14ff60e01b81526001600160a01b0382166004820152336024820152604401610423565b60405163aee758e760e01b81527f4714fd9784ca8c9ee16df7000f2eb0fc7a2296e457de6968bc65d71fd28737066004820152600090612710906001600160a01b037f000000000000000000000000f764442856eb3fe68a0828e07246a4b395e800fa169063aee758e790602401602060405180830381865afa15801561095f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109839190610f5b565b6109919061ffff1685610ecc565b61099b9190610ee3565b60405163a443a63560e01b815260048101889052602481018290526001600160a01b0387811660448301529192507f00000000000000000000000089bc08ba00f135d608bc335f6b33d7a9abcc98af9091169063a443a63590606401600060405180830381600087803b158015610a1157600080fd5b505af1158015610a25573d6000803e3d6000fd5b50505050505050505050565b60008060007f00000000000000000000000089bc08ba00f135d608bc335f6b33d7a9abcc98af6001600160a01b031663504006ca856040518263ffffffff1660e01b8152600401610a8491815260200190565b6101a060405180830381865afa158015610aa2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac69190610d7e565b9050600081516003811115610add57610add610e69565b03610afe57604051630fd8a76760e01b815260048101859052602401610423565b600181516003811115610b1357610b13610e69565b14610b34578051604051631b250a6b60e11b81526104239190600401610f33565b604081015160208101518151600091610b4c91610648565b9050600061271084606001516020015161ffff1683610b6b9190610ecc565b610b759190610ee3565b9050600061271085606001516040015161ffff168560200151610b989190610ecc565b610ba29190610ee3565b9050828460200151610bb49190610eb9565b965080610bc18389610f76565b610bcb9190610f76565b95505050505050915091565b600060208284031215610be957600080fd5b5035919050565b60008060408385031215610c0357600080fd5b50508035926020909101359150565b6001600160a01b0381168114610c2757600080fd5b50565b60008060408385031215610c3d57600080fd5b823591506020830135610c4f81610c12565b809150509250929050565b6040516080810167ffffffffffffffff81118282101715610c8b57634e487b7160e01b600052604160045260246000fd5b60405290565b604051610100810167ffffffffffffffff81118282101715610c8b57634e487b7160e01b600052604160045260246000fd5b8051610cce81610c12565b919050565b80516bffffffffffffffffffffffff81168114610cce57600080fd5b805161ffff81168114610cce57600080fd5b600060608284031215610d1357600080fd5b6040516060810181811067ffffffffffffffff82111715610d4457634e487b7160e01b600052604160045260246000fd5b604052905080610d5383610cef565b8152610d6160208401610cef565b6020820152610d7260408401610cef565b60408201525092915050565b60008183036101a0811215610d9257600080fd5b610d9a610c5a565b835160048110610da957600080fd5b81526020840151610db981610c12565b6020820152610100603f198301811315610dd257600080fd5b610dda610c91565b925060408501518352606085015160208401526080850151610dfb81610c12565b6040840152610e0c60a08601610cd3565b606084015260c08501516080840152610e2760e08601610cc3565b60a0840152610e37818601610cd3565b60c08401525061012084015160e0830152816040820152610e5c856101408601610d01565b6060820152949350505050565b634e487b7160e01b600052602160045260246000fd5b600060208284031215610e9157600080fd5b8151610e9c81610c12565b9392505050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561067557610675610ea3565b808202811582820484141761067557610675610ea3565b600082610f0057634e487b7160e01b600052601260045260246000fd5b500490565b60008060408385031215610f1857600080fd5b8251610f2381610c12565b6020939093015192949293505050565b6020810160048310610f5557634e487b7160e01b600052602160045260246000fd5b91905290565b600060208284031215610f6d57600080fd5b61067282610cef565b8181038181111561067557610675610ea356fea164736f6c6343000812000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000089bc08ba00f135d608bc335f6b33d7a9abcc98af000000000000000000000000f764442856eb3fe68a0828e07246a4b395e800fa
-----Decoded View---------------
Arg [0] : _loanCore (address): 0x89bc08BA00f135d608bc335f6B33D7a9ABCC98aF
Arg [1] : _feeController (address): 0xf764442856Eb3fe68A0828e07246a4B395e800fa
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000089bc08ba00f135d608bc335f6b33d7a9abcc98af
Arg [1] : 000000000000000000000000f764442856eb3fe68a0828e07246a4b395e800fa
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.