Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x61192761 | 14443196 | 908 days ago | IN | 0 ETH | 0.05776172 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
NFTfiSigningUtils
Compiler Version
v0.8.4+commit.c7e474f2
Optimization Enabled:
Yes with 100 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.4; import "../interfaces/IBundleBuilder.sol"; import "../loans/direct/loanTypes/LoanData.sol"; import "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol"; /** * @title NFTfiSigningUtils * @author NFTfi * @notice Helper contract for NFTfi. This contract manages verifying signatures from off-chain NFTfi orders. * Based on the version of this same contract used on NFTfi V1 */ library NFTfiSigningUtils { /* ********* */ /* FUNCTIONS */ /* ********* */ /** * @dev This function gets the current chain ID. */ function getChainID() public view returns (uint256) { uint256 id; // solhint-disable-next-line no-inline-assembly assembly { id := chainid() } return id; } /** * @notice This function is when the lender accepts a borrower's binding listing terms, to validate the lender's * signature that the borrower provided off-chain to verify that it did indeed made such listing. * * @param _listingTerms - The listing terms struct containing: * - loanERC20Denomination: The address of the ERC20 contract of the currency being used as principal/interest * for this loan. * - minLoanPrincipalAmount: The minumum sum of money transferred from lender to borrower at the beginning of * the loan, measured in loanERC20Denomination's smallest units. * - maxLoanPrincipalAmount: The sum of money transferred from lender to borrower at the beginning of * the loan, measured in loanERC20Denomination's smallest units. * - maximumRepaymentAmount: The maximum amount of money that the borrower would be required to retrieve their * collateral, measured in the smallest units of the ERC20 currency used for the loan. The borrower will always have * to pay this amount to retrieve their collateral, regardless of whether they repay early. * - nftCollateralContract: The address of the ERC721 contract of the NFT collateral. * - nftCollateralId: The ID within the NFTCollateralContract for the NFT being used as collateral for this * loan. The NFT is stored within this contract during the duration of the loan. * - revenueSharePartner: The address of the partner that will receive the revenue share. * - minLoanDuration: The minumum amount of time (measured in seconds) that can elapse before the lender can * liquidate the loan and seize the underlying collateral NFT. * - maxLoanDuration: The maximum amount of time (measured in seconds) that can elapse before the lender can * liquidate the loan and seize the underlying collateral NFT. * - maxInterestRateForDurationInBasisPoints: This is maximum the interest rate (measured in basis points, e.g. * hundreths of a percent) for the loan, that must be repaid pro-rata by the borrower at the conclusion of the loan * or risk seizure of their nft collateral. Note if the type of the loan is fixed then this value is not used and * is irrelevant so it should be set to 0. * - referralFeeInBasisPoints: The percent (measured in basis points) of the loan principal amount that will be * taken as a fee to pay to the referrer, 0 if the lender is not paying referral fee. * @param _signature - The offer struct containing: * - signer: The address of the signer. The borrower for `acceptOffer` the lender for `acceptListing`. * - nonce: The nonce referred here is not the same as an Ethereum account's nonce. * We are referring instead to a nonce that is used by the lender or the borrower when they are first signing * off-chain NFTfi orders. These nonce can be any uint256 value that the user has not previously used to sign an * off-chain order. Each nonce can be used at most once per user within NFTfi, regardless of whether they are the * lender or the borrower in that situation. This serves two purposes: * - First, it prevents replay attacks where an attacker would submit a user's off-chain order more than once. * - Second, it allows a user to cancel an off-chain order by calling * NFTfi.cancelLoanCommitmentBeforeLoanHasBegun(), which marks the nonce as used and prevents any future loan from * using the user's off-chain order that contains that nonce. * - expiry: Date when the signature expires * - signature: The ECDSA signature of the borrower, obtained off-chain ahead of time, signing the following * combination of parameters: * - listingTerms.loanERC20Denomination, * - listingTerms.minLoanPrincipalAmount, * - listingTerms.maxLoanPrincipalAmount, * - listingTerms.nftCollateralContract, * - listingTerms.nftCollateralId, * - listingTerms.revenueSharePartner, * - listingTerms.minLoanDuration, * - listingTerms.maxLoanDuration, * - listingTerms.maxInterestRateForDurationInBasisPoints, * - listingTerms.referralFeeInBasisPoints, * - signature.signer, * - signature.nonce, * - signature.expiry, * - address of this contract * - chainId */ function isValidBorrowerSignature(LoanData.ListingTerms memory _listingTerms, LoanData.Signature memory _signature) external view returns (bool) { return isValidBorrowerSignature(_listingTerms, _signature, address(this)); } /** * @dev This function overload the previous function to allow the caller to specify the address of the contract * */ function isValidBorrowerSignature( LoanData.ListingTerms memory _listingTerms, LoanData.Signature memory _signature, address _loanContract ) public view returns (bool) { require(block.timestamp <= _signature.expiry, "Borrower Signature has expired"); require(_loanContract != address(0), "Loan is zero address"); if (_signature.signer == address(0)) { return false; } else { bytes32 message = keccak256( abi.encodePacked( getEncodedListing(_listingTerms), getEncodedSignature(_signature), _loanContract, getChainID() ) ); return SignatureChecker.isValidSignatureNow( _signature.signer, ECDSA.toEthSignedMessageHash(message), _signature.signature ); } } /** * @notice This function is when the lender accepts a borrower's binding listing terms, to validate the lender's * signature that the borrower provided off-chain to verify that it did indeed made such listing. * * @param _listingTerms - The listing terms struct containing: * - loanERC20Denomination: The address of the ERC20 contract of the currency being used as principal/interest * for this loan. * - minLoanPrincipalAmount: The minumum sum of money transferred from lender to borrower at the beginning of * the loan, measured in loanERC20Denomination's smallest units. * - maxLoanPrincipalAmount: The sum of money transferred from lender to borrower at the beginning of * the loan, measured in loanERC20Denomination's smallest units. * - maximumRepaymentAmount: The maximum amount of money that the borrower would be required to retrieve their * collateral, measured in the smallest units of the ERC20 currency used for the loan. The borrower will always have * to pay this amount to retrieve their collateral, regardless of whether they repay early. * - nftCollateralContract: The address of the ERC721 contract of the NFT collateral. * - nftCollateralId: The ID within the NFTCollateralContract for the NFT being used as collateral for this * loan. The NFT is stored within this contract during the duration of the loan. * - revenueSharePartner: The address of the partner that will receive the revenue share. * - minLoanDuration: The minumum amount of time (measured in seconds) that can elapse before the lender can * liquidate the loan and seize the underlying collateral NFT. * - maxLoanDuration: The maximum amount of time (measured in seconds) that can elapse before the lender can * liquidate the loan and seize the underlying collateral NFT. * - maxInterestRateForDurationInBasisPoints: This is maximum the interest rate (measured in basis points, e.g. * hundreths of a percent) for the loan, that must be repaid pro-rata by the borrower at the conclusion of the loan * or risk seizure of their nft collateral. Note if the type of the loan is fixed then this value is not used and * is irrelevant so it should be set to 0. * - referralFeeInBasisPoints: The percent (measured in basis points) of the loan principal amount that will be * taken as a fee to pay to the referrer, 0 if the lender is not paying referral fee. * @param _bundleElements - the lists of erc721-20-1155 tokens that are to be bundled * @param _signature - The offer struct containing: * - signer: The address of the signer. The borrower for `acceptOffer` the lender for `acceptListing`. * - nonce: The nonce referred here is not the same as an Ethereum account's nonce. * We are referring instead to a nonce that is used by the lender or the borrower when they are first signing * off-chain NFTfi orders. These nonce can be any uint256 value that the user has not previously used to sign an * off-chain order. Each nonce can be used at most once per user within NFTfi, regardless of whether they are the * lender or the borrower in that situation. This serves two purposes: * - First, it prevents replay attacks where an attacker would submit a user's off-chain order more than once. * - Second, it allows a user to cancel an off-chain order by calling * NFTfi.cancelLoanCommitmentBeforeLoanHasBegun(), which marks the nonce as used and prevents any future loan from * using the user's off-chain order that contains that nonce. * - expiry: Date when the signature expires * - signature: The ECDSA signature of the borrower, obtained off-chain ahead of time, signing the following * combination of parameters: * - listingTerms.loanERC20Denomination, * - listingTerms.minLoanPrincipalAmount, * - listingTerms.maxLoanPrincipalAmount, * - listingTerms.nftCollateralContract, * - listingTerms.nftCollateralId, * - listingTerms.revenueSharePartner, * - listingTerms.minLoanDuration, * - listingTerms.maxLoanDuration, * - listingTerms.maxInterestRateForDurationInBasisPoints, * - listingTerms.referralFeeInBasisPoints, * - bundleElements * - signature.signer, * - signature.nonce, * - signature.expiry, * - address of this contract * - chainId */ function isValidBorrowerSignatureBundle( LoanData.ListingTerms memory _listingTerms, IBundleBuilder.BundleElements memory _bundleElements, LoanData.Signature memory _signature ) external view returns (bool) { return isValidBorrowerSignatureBundle(_listingTerms, _bundleElements, _signature, address(this)); } /** * @dev This function overload the previous function to allow the caller to specify the address of the contract * */ function isValidBorrowerSignatureBundle( LoanData.ListingTerms memory _listingTerms, IBundleBuilder.BundleElements memory _bundleElements, LoanData.Signature memory _signature, address _loanContract ) public view returns (bool) { require(block.timestamp <= _signature.expiry, "Borrower Signature has expired"); require(_loanContract != address(0), "Loan is zero address"); if (_signature.signer == address(0)) { return false; } else { bytes32 message = keccak256( abi.encodePacked( getEncodedListing(_listingTerms), abi.encode(_bundleElements), getEncodedSignature(_signature), _loanContract, getChainID() ) ); return SignatureChecker.isValidSignatureNow( _signature.signer, ECDSA.toEthSignedMessageHash(message), _signature.signature ); } } /** * @notice This function is when the borrower accepts a lender's offer, to validate the lender's signature that the * lender provided off-chain to verify that it did indeed made such offer. * * @param _offer - The offer struct containing: * - loanERC20Denomination: The address of the ERC20 contract of the currency being used as principal/interest * for this loan. * - loanPrincipalAmount: The original sum of money transferred from lender to borrower at the beginning of * the loan, measured in loanERC20Denomination's smallest units. * - maximumRepaymentAmount: The maximum amount of money that the borrower would be required to retrieve their * collateral, measured in the smallest units of the ERC20 currency used for the loan. The borrower will always have * to pay this amount to retrieve their collateral, regardless of whether they repay early. * - nftCollateralContract: The address of the ERC721 contract of the NFT collateral. * - nftCollateralId: The ID within the NFTCollateralContract for the NFT being used as collateral for this * loan. The NFT is stored within this contract during the duration of the loan. * - referrer: The address of the referrer who found the lender matching the listing, Zero address to signal * this there is no referrer. * - loanDuration: The amount of time (measured in seconds) that can elapse before the lender can liquidate the * loan and seize the underlying collateral NFT. * - loanInterestRateForDurationInBasisPoints: This is the interest rate (measured in basis points, e.g. * hundreths of a percent) for the loan, that must be repaid pro-rata by the borrower at the conclusion of the loan * or risk seizure of their nft collateral. Note if the type of the loan is fixed then this value is not used and * is irrelevant so it should be set to 0. * - loanAdminFeeInBasisPoints: The percent (measured in basis points) of the interest earned that will be * taken as a fee by the contract admins when the loan is repaid. The fee is stored in the loan struct to prevent an * attack where the contract admins could adjust the fee right before a loan is repaid, and take all of the interest * earned. * @param _signature - The signature structure containing: * - signer: The address of the signer. The borrower for `acceptOffer` the lender for `acceptListing`. * - nonce: The nonce referred here is not the same as an Ethereum account's nonce. * We are referring instead to a nonce that is used by the lender or the borrower when they are first signing * off-chain NFTfi orders. These nonce can be any uint256 value that the user has not previously used to sign an * off-chain order. Each nonce can be used at most once per user within NFTfi, regardless of whether they are the * lender or the borrower in that situation. This serves two purposes: * - First, it prevents replay attacks where an attacker would submit a user's off-chain order more than once. * - Second, it allows a user to cancel an off-chain order by calling * NFTfi.cancelLoanCommitmentBeforeLoanHasBegun(), which marks the nonce as used and prevents any future loan from * using the user's off-chain order that contains that nonce. * - expiry: Date when the signature expires * - signature: The ECDSA signature of the lender, obtained off-chain ahead of time, signing the following * combination of parameters: * - offer.loanERC20Denomination * - offer.loanPrincipalAmount * - offer.maximumRepaymentAmount * - offer.nftCollateralContract * - offer.nftCollateralId * - offer.referrer * - offer.loanDuration * - offer.loanAdminFeeInBasisPoints * - signature.signer, * - signature.nonce, * - signature.expiry, * - address of this contract * - chainId */ function isValidLenderSignature(LoanData.Offer memory _offer, LoanData.Signature memory _signature) external view returns (bool) { return isValidLenderSignature(_offer, _signature, address(this)); } /** * @dev This function overload the previous function to allow the caller to specify the address of the contract * */ function isValidLenderSignature( LoanData.Offer memory _offer, LoanData.Signature memory _signature, address _loanContract ) public view returns (bool) { require(block.timestamp <= _signature.expiry, "Lender Signature has expired"); require(_loanContract != address(0), "Loan is zero address"); if (_signature.signer == address(0)) { return false; } else { bytes32 message = keccak256( abi.encodePacked(getEncodedOffer(_offer), getEncodedSignature(_signature), _loanContract, getChainID()) ); return SignatureChecker.isValidSignatureNow( _signature.signer, ECDSA.toEthSignedMessageHash(message), _signature.signature ); } } /** * @notice This function is when the borrower accepts a lender's offer, to validate the lender's signature that the * lender provided off-chain to verify that it did indeed made such offer. * * @param _offer - The offer struct containing: * - loanERC20Denomination: The address of the ERC20 contract of the currency being used as principal/interest * for this loan. * - loanPrincipalAmount: The original sum of money transferred from lender to borrower at the beginning of * the loan, measured in loanERC20Denomination's smallest units. * - maximumRepaymentAmount: The maximum amount of money that the borrower would be required to retrieve their * collateral, measured in the smallest units of the ERC20 currency used for the loan. The borrower will always have * to pay this amount to retrieve their collateral, regardless of whether they repay early. * - nftCollateralContract: The address of the ERC721 contract of the NFT collateral. * - nftCollateralId: The ID within the NFTCollateralContract for the NFT being used as collateral for this * loan. The NFT is stored within this contract during the duration of the loan. * - referrer: The address of the referrer who found the lender matching the listing, Zero address to signal * this there is no referrer. * - loanDuration: The amount of time (measured in seconds) that can elapse before the lender can liquidate the * loan and seize the underlying collateral NFT. * - loanInterestRateForDurationInBasisPoints: This is the interest rate (measured in basis points, e.g. * hundreths of a percent) for the loan, that must be repaid pro-rata by the borrower at the conclusion of the loan * or risk seizure of their nft collateral. Note if the type of the loan is fixed then this value is not used and * is irrelevant so it should be set to 0. * - loanAdminFeeInBasisPoints: The percent (measured in basis points) of the interest earned that will be * taken as a fee by the contract admins when the loan is repaid. The fee is stored in the loan struct to prevent an * attack where the contract admins could adjust the fee right before a loan is repaid, and take all of the interest * earned. * @param _bundleElements - the lists of erc721-20-1155 tokens that are to be bundled * @param _signature - The signature structure containing: * - signer: The address of the signer. The borrower for `acceptOffer` the lender for `acceptListing`. * - nonce: The nonce referred here is not the same as an Ethereum account's nonce. * We are referring instead to a nonce that is used by the lender or the borrower when they are first signing * off-chain NFTfi orders. These nonce can be any uint256 value that the user has not previously used to sign an * off-chain order. Each nonce can be used at most once per user within NFTfi, regardless of whether they are the * lender or the borrower in that situation. This serves two purposes: * - First, it prevents replay attacks where an attacker would submit a user's off-chain order more than once. * - Second, it allows a user to cancel an off-chain order by calling * NFTfi.cancelLoanCommitmentBeforeLoanHasBegun(), which marks the nonce as used and prevents any future loan from * using the user's off-chain order that contains that nonce. * - expiry: Date when the signature expires * - signature: The ECDSA signature of the lender, obtained off-chain ahead of time, signing the following * combination of parameters: * - offer.loanERC20Denomination * - offer.loanPrincipalAmount * - offer.maximumRepaymentAmount * - offer.nftCollateralContract * - offer.nftCollateralId * - offer.referrer * - offer.loanDuration * - offer.loanAdminFeeInBasisPoints * - bundleElements * - signature.signer, * - signature.nonce, * - signature.expiry, * - address of this contract * - chainId */ function isValidLenderSignatureBundle( LoanData.Offer memory _offer, IBundleBuilder.BundleElements memory _bundleElements, LoanData.Signature memory _signature ) external view returns (bool) { return isValidLenderSignatureBundle(_offer, _bundleElements, _signature, address(this)); } /** * @dev This function overload the previous function to allow the caller to specify the address of the contract * */ function isValidLenderSignatureBundle( LoanData.Offer memory _offer, IBundleBuilder.BundleElements memory _bundleElements, LoanData.Signature memory _signature, address _loanContract ) public view returns (bool) { require(block.timestamp <= _signature.expiry, "Lender Signature has expired"); require(_loanContract != address(0), "Loan is zero address"); if (_signature.signer == address(0)) { return false; } else { bytes32 message = keccak256( abi.encodePacked( getEncodedOffer(_offer), abi.encode(_bundleElements), getEncodedSignature(_signature), _loanContract, getChainID() ) ); return SignatureChecker.isValidSignatureNow( _signature.signer, ECDSA.toEthSignedMessageHash(message), _signature.signature ); } } /** * @notice This function is called in renegotiateLoan() to validate the lender's signature that the lender provided * off-chain to verify that they did indeed want to agree to this loan renegotiation according to these terms. * * @param _loanId - The unique identifier for the loan to be renegotiated * @param _newLoanDuration - The new amount of time (measured in seconds) that can elapse before the lender can * liquidate the loan and seize the underlying collateral NFT. * @param _newMaximumRepaymentAmount - The new maximum amount of money that the borrower would be required to * retrieve their collateral, measured in the smallest units of the ERC20 currency used for the loan. The * borrower will always have to pay this amount to retrieve their collateral, regardless of whether they repay * early. * @param _renegotiationFee Agreed upon fee in ether that borrower pays for the lender for the renegitiation * @param _signature - The signature structure containing: * - signer: The address of the signer. The borrower for `acceptOffer` the lender for `acceptListing`. * - nonce: The nonce referred here is not the same as an Ethereum account's nonce. * We are referring instead to a nonce that is used by the lender or the borrower when they are first signing * off-chain NFTfi orders. These nonce can be any uint256 value that the user has not previously used to sign an * off-chain order. Each nonce can be used at most once per user within NFTfi, regardless of whether they are the * lender or the borrower in that situation. This serves two purposes: * - First, it prevents replay attacks where an attacker would submit a user's off-chain order more than once. * - Second, it allows a user to cancel an off-chain order by calling NFTfi.cancelLoanCommitmentBeforeLoanHasBegun() * , which marks the nonce as used and prevents any future loan from using the user's off-chain order that contains * that nonce. * - expiry - The date when the renegotiation offer expires * - lenderSignature - The ECDSA signature of the lender, obtained off-chain ahead of time, signing the * following combination of parameters: * - _loanId * - _newLoanDuration * - _newMaximumRepaymentAmount * - _lender * - _lenderNonce * - _expiry * - address of this contract * - chainId */ function isValidLenderRenegotiationSignature( uint256 _loanId, uint32 _newLoanDuration, uint256 _newMaximumRepaymentAmount, uint256 _renegotiationFee, LoanData.Signature memory _signature ) external view returns (bool) { return isValidLenderRenegotiationSignature( _loanId, _newLoanDuration, _newMaximumRepaymentAmount, _renegotiationFee, _signature, address(this) ); } /** * @dev This function overload the previous function to allow the caller to specify the address of the contract * */ function isValidLenderRenegotiationSignature( uint256 _loanId, uint32 _newLoanDuration, uint256 _newMaximumRepaymentAmount, uint256 _renegotiationFee, LoanData.Signature memory _signature, address _loanContract ) public view returns (bool) { require(block.timestamp <= _signature.expiry, "Renegotiation Signature has expired"); require(_loanContract != address(0), "Loan is zero address"); if (_signature.signer == address(0)) { return false; } else { bytes32 message = keccak256( abi.encodePacked( _loanId, _newLoanDuration, _newMaximumRepaymentAmount, _renegotiationFee, getEncodedSignature(_signature), _loanContract, getChainID() ) ); return SignatureChecker.isValidSignatureNow( _signature.signer, ECDSA.toEthSignedMessageHash(message), _signature.signature ); } } /** * @dev We need this to avoid stack too deep errors. */ function getEncodedListing(LoanData.ListingTerms memory _listingTerms) internal pure returns (bytes memory) { return abi.encodePacked( _listingTerms.loanERC20Denomination, _listingTerms.minLoanPrincipalAmount, _listingTerms.maxLoanPrincipalAmount, _listingTerms.nftCollateralContract, _listingTerms.nftCollateralId, _listingTerms.revenueSharePartner, _listingTerms.minLoanDuration, _listingTerms.maxLoanDuration, _listingTerms.maxInterestRateForDurationInBasisPoints, _listingTerms.referralFeeInBasisPoints ); } /** * @dev We need this to avoid stack too deep errors. */ function getEncodedOffer(LoanData.Offer memory _offer) internal pure returns (bytes memory) { return abi.encodePacked( _offer.loanERC20Denomination, _offer.loanPrincipalAmount, _offer.maximumRepaymentAmount, _offer.nftCollateralContract, _offer.nftCollateralId, _offer.referrer, _offer.loanDuration, _offer.loanAdminFeeInBasisPoints ); } /** * @dev We need this to avoid stack too deep errors. */ function getEncodedSignature(LoanData.Signature memory _signature) internal pure returns (bytes memory) { return abi.encodePacked(_signature.signer, _signature.nonce, _signature.expiry); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.4; interface IBundleBuilder { /** * @notice data of a erc721 bundle element * * @param tokenContract - address of the token contract * @param id - id of the token * @param safeTransferable - wether the implementing token contract has a safeTransfer function or not */ struct BundleElementERC721 { address tokenContract; uint256 id; bool safeTransferable; } /** * @notice data of a erc20 bundle element * * @param tokenContract - address of the token contract * @param amount - amount of the token */ struct BundleElementERC20 { address tokenContract; uint256 amount; } /** * @notice data of a erc20 bundle element * * @param tokenContract - address of the token contract * @param ids - list of ids of the tokens * @param amounts - list amounts of the tokens */ struct BundleElementERC1155 { address tokenContract; uint256[] ids; uint256[] amounts; } /** * @notice the lists of erc721-20-1155 tokens that are to be bundled * * @param erc721s list of erc721 tokens * @param erc20s list of erc20 tokens * @param erc1155s list of erc1155 tokens */ struct BundleElements { BundleElementERC721[] erc721s; BundleElementERC20[] erc20s; BundleElementERC1155[] erc1155s; } /** * @notice used by the loan contract to build a bundle from the BundleElements struct at the beginning of a loan, * returns the id of the created bundle * * @param _bundleElements - the lists of erc721-20-1155 tokens that are to be bundled * @param _sender sender of the tokens in the bundle - the borrower * @param _receiver receiver of the created bundle, normally the loan contract */ function buildBundle( BundleElements memory _bundleElements, address _sender, address _receiver ) external returns (uint256); /** * @notice Remove all the children from the bundle * @dev This method may run out of gas if the list of children is too big. In that case, children can be removed * individually. * @param _tokenId the id of the bundle * @param _receiver address of the receiver of the children */ function decomposeBundle(uint256 _tokenId, address _receiver) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.4; /** * @title LoanData * @author NFTfi * @notice An interface containg the main Loan struct shared by Direct Loans types. */ interface LoanData { /* ********** */ /* DATA TYPES */ /* ********** */ /** * @notice The main Loan Terms struct. This data is saved upon loan creation. * * @param loanERC20Denomination - The address of the ERC20 contract of the currency being used as principal/interest * for this loan. * @param loanPrincipalAmount - The original sum of money transferred from lender to borrower at the beginning of * the loan, measured in loanERC20Denomination's smallest units. * @param maximumRepaymentAmount - The maximum amount of money that the borrower would be required to retrieve their * collateral, measured in the smallest units of the ERC20 currency used for the loan. The borrower will always have * to pay this amount to retrieve their collateral, regardless of whether they repay early. * @param nftCollateralContract - The address of the the NFT collateral contract. * @param nftCollateralWrapper - The NFTfi wrapper of the NFT collateral contract. * @param nftCollateralId - The ID within the NFTCollateralContract for the NFT being used as collateral for this * loan. The NFT is stored within this contract during the duration of the loan. * @param loanStartTime - The block.timestamp when the loan first began (measured in seconds). * @param loanDuration - The amount of time (measured in seconds) that can elapse before the lender can liquidate * the loan and seize the underlying collateral NFT. * @param loanInterestRateForDurationInBasisPoints - This is the interest rate (measured in basis points, e.g. * hundreths of a percent) for the loan, that must be repaid pro-rata by the borrower at the conclusion of the loan * or risk seizure of their nft collateral. Note if the type of the loan is fixed then this value is not used and * is irrelevant so it should be set to 0. * @param loanAdminFeeInBasisPoints - The percent (measured in basis points) of the interest earned that will be * taken as a fee by the contract admins when the loan is repaid. The fee is stored in the loan struct to prevent an * attack where the contract admins could adjust the fee right before a loan is repaid, and take all of the interest * earned. * @param borrower */ struct LoanTerms { uint256 loanPrincipalAmount; uint256 maximumRepaymentAmount; uint256 nftCollateralId; address loanERC20Denomination; uint32 loanDuration; uint16 loanInterestRateForDurationInBasisPoints; uint16 loanAdminFeeInBasisPoints; address nftCollateralWrapper; uint64 loanStartTime; address nftCollateralContract; address borrower; } /** * @notice Some extra Loan's settings struct. This data is saved upon loan creation. * We need this to avoid stack too deep errors. * * @param revenueSharePartner - The address of the partner that will receive the revenue share. * @param revenueShareInBasisPoints - The percent (measured in basis points) of the admin fee amount that will be * taken as a revenue share for a t * @param referralFeeInBasisPoints - The percent (measured in basis points) of the loan principal amount that will * be taken as a fee to pay to the referrer, 0 if the lender is not paying referral fee.he partner, at the moment * the loan is begun. */ struct LoanExtras { address revenueSharePartner; uint16 revenueShareInBasisPoints; uint16 referralFeeInBasisPoints; } /** * @notice The offer made by the lender. Used as parameter on both acceptOffer (initiated by the borrower) and * acceptListing (initiated by the lender). * * @param loanERC20Denomination - The address of the ERC20 contract of the currency being used as principal/interest * for this loan. * @param loanPrincipalAmount - The original sum of money transferred from lender to borrower at the beginning of * the loan, measured in loanERC20Denomination's smallest units. * @param maximumRepaymentAmount - The maximum amount of money that the borrower would be required to retrieve their * collateral, measured in the smallest units of the ERC20 currency used for the loan. The borrower will always * have to pay this amount to retrieve their collateral, regardless of whether they repay early. * @param nftCollateralContract - The address of the ERC721 contract of the NFT collateral. * @param nftCollateralId - The ID within the NFTCollateralContract for the NFT being used as collateral for this * loan. The NFT is stored within this contract during the duration of the loan. * @param referrer - The address of the referrer who found the lender matching the listing, Zero address to signal * this there is no referrer. * @param loanDuration - The amount of time (measured in seconds) that can elapse before the lender can liquidate * the loan and seize the underlying collateral NFT. * @param loanAdminFeeInBasisPoints - The percent (measured in basis points) of the interest earned that will be * taken as a fee by the contract admins when the loan is repaid. The fee is stored in the loan struct to prevent an * attack where the contract admins could adjust the fee right before a loan is repaid, and take all of the interest * earned. */ struct Offer { uint256 loanPrincipalAmount; uint256 maximumRepaymentAmount; uint256 nftCollateralId; address nftCollateralContract; uint32 loanDuration; uint16 loanAdminFeeInBasisPoints; address loanERC20Denomination; address referrer; } /** * @notice Signature related params. Used as parameter on both acceptOffer (containing borrower signature) and * acceptListing (containing lender signature). * * @param signer - The address of the signer. The borrower for `acceptOffer` the lender for `acceptListing`. * @param nonce - The nonce referred here is not the same as an Ethereum account's nonce. * We are referring instead to a nonce that is used by the lender or the borrower when they are first signing * off-chain NFTfi orders. These nonce can be any uint256 value that the user has not previously used to sign an * off-chain order. Each nonce can be used at most once per user within NFTfi, regardless of whether they are the * lender or the borrower in that situation. This serves two purposes: * - First, it prevents replay attacks where an attacker would submit a user's off-chain order more than once. * - Second, it allows a user to cancel an off-chain order by calling NFTfi.cancelLoanCommitmentBeforeLoanHasBegun() * , which marks the nonce as used and prevents any future loan from using the user's off-chain order that contains * that nonce. * @param expiry - Date when the signature expires * @param signature - The ECDSA signature of the borrower or the lender, obtained off-chain ahead of time, signing * the following combination of parameters: * - Borrower * - ListingTerms.loanERC20Denomination, * - ListingTerms.minLoanPrincipalAmount, * - ListingTerms.maxLoanPrincipalAmount, * - ListingTerms.nftCollateralContract, * - ListingTerms.nftCollateralId, * - ListingTerms.revenueSharePartner, * - ListingTerms.minLoanDuration, * - ListingTerms.maxLoanDuration, * - ListingTerms.maxInterestRateForDurationInBasisPoints, * - ListingTerms.referralFeeInBasisPoints, * - Signature.signer, * - Signature.nonce, * - Signature.expiry, * - address of the loan type contract * - chainId * - Lender: * - Offer.loanERC20Denomination * - Offer.loanPrincipalAmount * - Offer.maximumRepaymentAmount * - Offer.nftCollateralContract * - Offer.nftCollateralId * - Offer.referrer * - Offer.loanDuration * - Offer.loanAdminFeeInBasisPoints * - Signature.signer, * - Signature.nonce, * - Signature.expiry, * - address of the loan type contract * - chainId */ struct Signature { uint256 nonce; uint256 expiry; address signer; bytes signature; } /** * @notice Some extra parameters that the borrower needs to set when accepting an offer. * * @param revenueSharePartner - The address of the partner that will receive the revenue share. * @param referralFeeInBasisPoints - The percent (measured in basis points) of the loan principal amount that will * be taken as a fee to pay to the referrer, 0 if the lender is not paying referral fee. */ struct BorrowerSettings { address revenueSharePartner; uint16 referralFeeInBasisPoints; } /** * @notice Terms the borrower set off-chain and is willing to accept automatically when fulfiled by a lender's * offer. * * @param loanERC20Denomination - The address of the ERC20 contract of the currency being used as principal/interest * for this loan. * @param minLoanPrincipalAmount - The minumum sum of money transferred from lender to borrower at the beginning of * the loan, measured in loanERC20Denomination's smallest units. * @param maxLoanPrincipalAmount - The sum of money transferred from lender to borrower at the beginning of * the loan, measured in loanERC20Denomination's smallest units. * @param maximumRepaymentAmount - The maximum amount of money that the borrower would be required to retrieve their * collateral, measured in the smallest units of the ERC20 currency used for the loan. The borrower will always have * to pay this amount to retrieve their collateral, regardless of whether they repay early. * @param nftCollateralContract - The address of the ERC721 contract of the NFT collateral. * @param nftCollateralId - The ID within the NFTCollateralContract for the NFT being used as collateral for this * loan. The NFT is stored within this contract during the duration of the loan. * @param revenueSharePartner - The address of the partner that will receive the revenue share. * @param minLoanDuration - The minumum amount of time (measured in seconds) that can elapse before the lender can * liquidate the loan and seize the underlying collateral NFT. * @param maxLoanDuration - The maximum amount of time (measured in seconds) that can elapse before the lender can * liquidate the loan and seize the underlying collateral NFT. * @param maxInterestRateForDurationInBasisPoints - This is maximum the interest rate (measured in basis points, * e.g. hundreths of a percent) for the loan. * @param referralFeeInBasisPoints - The percent (measured in basis points) of the loan principal amount that will * be taken as a fee to pay to the referrer, 0 if the lender is not paying referral fee. */ struct ListingTerms { uint256 minLoanPrincipalAmount; uint256 maxLoanPrincipalAmount; uint256 nftCollateralId; address nftCollateralContract; uint32 minLoanDuration; uint32 maxLoanDuration; uint16 maxInterestRateForDurationInBasisPoints; uint16 referralFeeInBasisPoints; address revenueSharePartner; address loanERC20Denomination; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/SignatureChecker.sol) pragma solidity ^0.8.0; import "./ECDSA.sol"; import "../Address.sol"; import "../../interfaces/IERC1271.sol"; /** * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like * Argent and Gnosis Safe. * * _Available since v4.1._ */ library SignatureChecker { /** * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`. * * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus * change through time. It could return true at block N and false at block N+1 (or the opposite). */ function isValidSignatureNow( address signer, bytes32 hash, bytes memory signature ) internal view returns (bool) { (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature); if (error == ECDSA.RecoverError.NoError && recovered == signer) { return true; } (bool success, bytes memory result) = signer.staticcall( abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature) ); return (success && result.length == 32 && abi.decode(result, (bytes4)) == IERC1271.isValidSignature.selector); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } else if (error == RecoverError.InvalidSignatureV) { revert("ECDSA: invalid signature 'v' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { // Check the signature length // - case 65: r,s,v signature (standard) // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._ if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else if (signature.length == 64) { bytes32 r; bytes32 vs; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) vs := mload(add(signature, 0x40)) } return tryRecover(hash, r, vs); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } if (v != 27 && v != 28) { return (address(0), RecoverError.InvalidSignatureV); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @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 * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 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 // OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC1271 standard signature validation method for * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. * * _Available since v4.1._ */ interface IERC1271 { /** * @dev Should return whether the signature provided is valid for the provided data * @param hash Hash of the data to be signed * @param signature Signature byte array associated with _data */ function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
{ "metadata": { "bytecodeHash": "none", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 100 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"getChainID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"minLoanPrincipalAmount","type":"uint256"},{"internalType":"uint256","name":"maxLoanPrincipalAmount","type":"uint256"},{"internalType":"uint256","name":"nftCollateralId","type":"uint256"},{"internalType":"address","name":"nftCollateralContract","type":"address"},{"internalType":"uint32","name":"minLoanDuration","type":"uint32"},{"internalType":"uint32","name":"maxLoanDuration","type":"uint32"},{"internalType":"uint16","name":"maxInterestRateForDurationInBasisPoints","type":"uint16"},{"internalType":"uint16","name":"referralFeeInBasisPoints","type":"uint16"},{"internalType":"address","name":"revenueSharePartner","type":"address"},{"internalType":"address","name":"loanERC20Denomination","type":"address"}],"internalType":"struct LoanData.ListingTerms","name":"_listingTerms","type":"tuple"},{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct LoanData.Signature","name":"_signature","type":"tuple"}],"name":"isValidBorrowerSignature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"minLoanPrincipalAmount","type":"uint256"},{"internalType":"uint256","name":"maxLoanPrincipalAmount","type":"uint256"},{"internalType":"uint256","name":"nftCollateralId","type":"uint256"},{"internalType":"address","name":"nftCollateralContract","type":"address"},{"internalType":"uint32","name":"minLoanDuration","type":"uint32"},{"internalType":"uint32","name":"maxLoanDuration","type":"uint32"},{"internalType":"uint16","name":"maxInterestRateForDurationInBasisPoints","type":"uint16"},{"internalType":"uint16","name":"referralFeeInBasisPoints","type":"uint16"},{"internalType":"address","name":"revenueSharePartner","type":"address"},{"internalType":"address","name":"loanERC20Denomination","type":"address"}],"internalType":"struct LoanData.ListingTerms","name":"_listingTerms","type":"tuple"},{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct LoanData.Signature","name":"_signature","type":"tuple"},{"internalType":"address","name":"_loanContract","type":"address"}],"name":"isValidBorrowerSignature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"minLoanPrincipalAmount","type":"uint256"},{"internalType":"uint256","name":"maxLoanPrincipalAmount","type":"uint256"},{"internalType":"uint256","name":"nftCollateralId","type":"uint256"},{"internalType":"address","name":"nftCollateralContract","type":"address"},{"internalType":"uint32","name":"minLoanDuration","type":"uint32"},{"internalType":"uint32","name":"maxLoanDuration","type":"uint32"},{"internalType":"uint16","name":"maxInterestRateForDurationInBasisPoints","type":"uint16"},{"internalType":"uint16","name":"referralFeeInBasisPoints","type":"uint16"},{"internalType":"address","name":"revenueSharePartner","type":"address"},{"internalType":"address","name":"loanERC20Denomination","type":"address"}],"internalType":"struct LoanData.ListingTerms","name":"_listingTerms","type":"tuple"},{"components":[{"components":[{"internalType":"address","name":"tokenContract","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"safeTransferable","type":"bool"}],"internalType":"struct IBundleBuilder.BundleElementERC721[]","name":"erc721s","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenContract","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IBundleBuilder.BundleElementERC20[]","name":"erc20s","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenContract","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"internalType":"struct IBundleBuilder.BundleElementERC1155[]","name":"erc1155s","type":"tuple[]"}],"internalType":"struct IBundleBuilder.BundleElements","name":"_bundleElements","type":"tuple"},{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct LoanData.Signature","name":"_signature","type":"tuple"}],"name":"isValidBorrowerSignatureBundle","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"minLoanPrincipalAmount","type":"uint256"},{"internalType":"uint256","name":"maxLoanPrincipalAmount","type":"uint256"},{"internalType":"uint256","name":"nftCollateralId","type":"uint256"},{"internalType":"address","name":"nftCollateralContract","type":"address"},{"internalType":"uint32","name":"minLoanDuration","type":"uint32"},{"internalType":"uint32","name":"maxLoanDuration","type":"uint32"},{"internalType":"uint16","name":"maxInterestRateForDurationInBasisPoints","type":"uint16"},{"internalType":"uint16","name":"referralFeeInBasisPoints","type":"uint16"},{"internalType":"address","name":"revenueSharePartner","type":"address"},{"internalType":"address","name":"loanERC20Denomination","type":"address"}],"internalType":"struct LoanData.ListingTerms","name":"_listingTerms","type":"tuple"},{"components":[{"components":[{"internalType":"address","name":"tokenContract","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"safeTransferable","type":"bool"}],"internalType":"struct IBundleBuilder.BundleElementERC721[]","name":"erc721s","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenContract","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IBundleBuilder.BundleElementERC20[]","name":"erc20s","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenContract","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"internalType":"struct IBundleBuilder.BundleElementERC1155[]","name":"erc1155s","type":"tuple[]"}],"internalType":"struct IBundleBuilder.BundleElements","name":"_bundleElements","type":"tuple"},{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct LoanData.Signature","name":"_signature","type":"tuple"},{"internalType":"address","name":"_loanContract","type":"address"}],"name":"isValidBorrowerSignatureBundle","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_loanId","type":"uint256"},{"internalType":"uint32","name":"_newLoanDuration","type":"uint32"},{"internalType":"uint256","name":"_newMaximumRepaymentAmount","type":"uint256"},{"internalType":"uint256","name":"_renegotiationFee","type":"uint256"},{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct LoanData.Signature","name":"_signature","type":"tuple"},{"internalType":"address","name":"_loanContract","type":"address"}],"name":"isValidLenderRenegotiationSignature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_loanId","type":"uint256"},{"internalType":"uint32","name":"_newLoanDuration","type":"uint32"},{"internalType":"uint256","name":"_newMaximumRepaymentAmount","type":"uint256"},{"internalType":"uint256","name":"_renegotiationFee","type":"uint256"},{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct LoanData.Signature","name":"_signature","type":"tuple"}],"name":"isValidLenderRenegotiationSignature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"loanPrincipalAmount","type":"uint256"},{"internalType":"uint256","name":"maximumRepaymentAmount","type":"uint256"},{"internalType":"uint256","name":"nftCollateralId","type":"uint256"},{"internalType":"address","name":"nftCollateralContract","type":"address"},{"internalType":"uint32","name":"loanDuration","type":"uint32"},{"internalType":"uint16","name":"loanAdminFeeInBasisPoints","type":"uint16"},{"internalType":"address","name":"loanERC20Denomination","type":"address"},{"internalType":"address","name":"referrer","type":"address"}],"internalType":"struct LoanData.Offer","name":"_offer","type":"tuple"},{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct LoanData.Signature","name":"_signature","type":"tuple"},{"internalType":"address","name":"_loanContract","type":"address"}],"name":"isValidLenderSignature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"loanPrincipalAmount","type":"uint256"},{"internalType":"uint256","name":"maximumRepaymentAmount","type":"uint256"},{"internalType":"uint256","name":"nftCollateralId","type":"uint256"},{"internalType":"address","name":"nftCollateralContract","type":"address"},{"internalType":"uint32","name":"loanDuration","type":"uint32"},{"internalType":"uint16","name":"loanAdminFeeInBasisPoints","type":"uint16"},{"internalType":"address","name":"loanERC20Denomination","type":"address"},{"internalType":"address","name":"referrer","type":"address"}],"internalType":"struct LoanData.Offer","name":"_offer","type":"tuple"},{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct LoanData.Signature","name":"_signature","type":"tuple"}],"name":"isValidLenderSignature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"loanPrincipalAmount","type":"uint256"},{"internalType":"uint256","name":"maximumRepaymentAmount","type":"uint256"},{"internalType":"uint256","name":"nftCollateralId","type":"uint256"},{"internalType":"address","name":"nftCollateralContract","type":"address"},{"internalType":"uint32","name":"loanDuration","type":"uint32"},{"internalType":"uint16","name":"loanAdminFeeInBasisPoints","type":"uint16"},{"internalType":"address","name":"loanERC20Denomination","type":"address"},{"internalType":"address","name":"referrer","type":"address"}],"internalType":"struct LoanData.Offer","name":"_offer","type":"tuple"},{"components":[{"components":[{"internalType":"address","name":"tokenContract","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"safeTransferable","type":"bool"}],"internalType":"struct IBundleBuilder.BundleElementERC721[]","name":"erc721s","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenContract","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IBundleBuilder.BundleElementERC20[]","name":"erc20s","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenContract","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"internalType":"struct IBundleBuilder.BundleElementERC1155[]","name":"erc1155s","type":"tuple[]"}],"internalType":"struct IBundleBuilder.BundleElements","name":"_bundleElements","type":"tuple"},{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct LoanData.Signature","name":"_signature","type":"tuple"},{"internalType":"address","name":"_loanContract","type":"address"}],"name":"isValidLenderSignatureBundle","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"loanPrincipalAmount","type":"uint256"},{"internalType":"uint256","name":"maximumRepaymentAmount","type":"uint256"},{"internalType":"uint256","name":"nftCollateralId","type":"uint256"},{"internalType":"address","name":"nftCollateralContract","type":"address"},{"internalType":"uint32","name":"loanDuration","type":"uint32"},{"internalType":"uint16","name":"loanAdminFeeInBasisPoints","type":"uint16"},{"internalType":"address","name":"loanERC20Denomination","type":"address"},{"internalType":"address","name":"referrer","type":"address"}],"internalType":"struct LoanData.Offer","name":"_offer","type":"tuple"},{"components":[{"components":[{"internalType":"address","name":"tokenContract","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"safeTransferable","type":"bool"}],"internalType":"struct IBundleBuilder.BundleElementERC721[]","name":"erc721s","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenContract","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IBundleBuilder.BundleElementERC20[]","name":"erc20s","type":"tuple[]"},{"components":[{"internalType":"address","name":"tokenContract","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"internalType":"struct IBundleBuilder.BundleElementERC1155[]","name":"erc1155s","type":"tuple[]"}],"internalType":"struct IBundleBuilder.BundleElements","name":"_bundleElements","type":"tuple"},{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct LoanData.Signature","name":"_signature","type":"tuple"}],"name":"isValidLenderSignatureBundle","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
61192761003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100b35760003560e01c806387c0a5731161007b57806387c0a57314610127578063a819956e1461013a578063c42129211461014d578063d06ff74114610160578063eb2ac63f14610173578063fb7a322a1461018657600080fd5b80632eb68793146100b85780633ce5ed9f146100e05780634051a17a146100f3578063564b81ef146101065780636ab81ec014610114575b600080fd5b6100cb6100c6366004610fa8565b610199565b60405190151581526020015b60405180910390f35b6100cb6100ee36600461101c565b6101b1565b6100cb6101013660046110a2565b6102a9565b6040514681526020016100d7565b6100cb61012236600461125f565b6102b6565b6100cb61013536600461131d565b610376565b6100cb6101483660046111ac565b610476565b6100cb61015b3660046110f0565b6104e7565b6100cb61016e3660046112b5565b610558565b6100cb610181366004611227565b610568565b6100cb61019436600461114f565b610575565b60006101a7848484306101b1565b90505b9392505050565b600082602001514211156101e05760405162461bcd60e51b81526004016101d79061168e565b60405180910390fd5b6001600160a01b0382166102065760405162461bcd60e51b81526004016101d7906116fc565b60408301516001600160a01b0316610220575060006102a1565b600061022b86610583565b8560405160200161023c919061172a565b604051602081830303815290604052610254866105e8565b854660405160200161026a95949392919061158e565b60405160208183030381529060405280519060200120905061029d84604001516102938361062b565b866060015161067e565b9150505b949350505050565b60006101aa8383306104e7565b600082602001514211156102dc5760405162461bcd60e51b81526004016101d7906116c5565b6001600160a01b0382166103025760405162461bcd60e51b81526004016101d7906116fc565b60408301516001600160a01b031661031c575060006101aa565b6000610327856107d8565b610330856105e8565b84466040516020016103459493929190611543565b60405160208183030381529060405280519060200120905061036e84604001516102938361062b565b9150506101aa565b600082602001514211156103d85760405162461bcd60e51b815260206004820152602360248201527f52656e65676f74696174696f6e205369676e61747572652068617320657870696044820152621c995960ea1b60648201526084016101d7565b6001600160a01b0382166103fe5760405162461bcd60e51b81526004016101d7906116fc565b60408301516001600160a01b03166104185750600061046c565b600087878787610427886105e8565b874660405160200161043f97969594939291906115ed565b60405160208183030381529060405280519060200120905061046884604001516102938361062b565b9150505b9695505050505050565b6000826020015142111561049c5760405162461bcd60e51b81526004016101d7906116c5565b6001600160a01b0382166104c25760405162461bcd60e51b81526004016101d7906116fc565b60408301516001600160a01b03166104dc575060006102a1565b600061022b866107d8565b6000826020015142111561050d5760405162461bcd60e51b81526004016101d79061168e565b6001600160a01b0382166105335760405162461bcd60e51b81526004016101d7906116fc565b60408301516001600160a01b031661054d575060006101aa565b600061032785610583565b600061046c868686868630610376565b60006101aa8383306102b6565b60006101a784848430610476565b6060816101200151826000015183602001518460600151856040015186610100015187608001518860a001518960c001518a60e001516040516020016105d29a99989796959493929190611491565b6040516020818303038152906040529050919050565b60608160400151826000015183602001516040516020016105d29392919060609390931b6001600160601b03191683526014830191909152603482015260540190565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b600080600061068d8585610881565b909250905060008160048111156106b457634e487b7160e01b600052602160045260246000fd5b1480156106d25750856001600160a01b0316826001600160a01b0316145b156106e2576001925050506101aa565b600080876001600160a01b0316631626ba7e60e01b888860405160240161070a929190611654565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516107489190611527565b600060405180830381855afa9150503d8060008114610783576040519150601f19603f3d011682016040523d82523d6000602084013e610788565b606091505b509150915081801561079b575080516020145b80156107cc57508051630b135d3f60e11b906107c09083016020908101908401610f80565b6001600160e01b031916145b98975050505050505050565b60608160c0015182600001518360200151846060015185604001518660e0015187608001518860a001516040516020016105d2989796959493929190606098891b6001600160601b031990811682526014820198909852603481019690965293871b86166054860152606885019290925290941b909216608882015260e09290921b6001600160e01b031916609c83015260f01b6001600160f01b03191660a082015260a20190565b6000808251604114156108b85760208301516040840151606085015160001a6108ac878285856108f1565b945094505050506108ea565b8251604014156108e257602083015160408401516108d78683836109d4565b9350935050506108ea565b506000905060025b9250929050565b6000806fa2a8918ca85bafe22016d0b997e4df60600160ff1b0383111561091e57506000905060036109cb565b8460ff16601b1415801561093657508460ff16601c14155b1561094757506000905060046109cb565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561099b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166109c4576000600192509250506109cb565b9150600090505b94509492505050565b6000806001600160ff1b038316816109f160ff86901c601b6118b0565b90506109ff878288856108f1565b935093505050935093915050565b80356001600160a01b0381168114610a2457600080fd5b919050565b600082601f830112610a39578081fd5b81356020610a4e610a498361188d565b61185d565b80838252828201915082860187848660051b8901011115610a6d578586fd5b855b85811015610b175781356001600160401b0380821115610a8d578889fd5b908901906060828c03601f1901811315610aa557898afd5b610aad6117ce565b610ab8898501610a0d565b815260408085013584811115610acc578c8dfd5b610ada8f8c83890101610baa565b838c015250918401359183831115610af0578b8cfd5b610afe8e8b85880101610baa565b9082015287525050509284019290840190600101610a6f565b5090979650505050505050565b600082601f830112610b34578081fd5b81356020610b44610a498361188d565b80838252828201915082860187848660061b8901011115610b63578586fd5b855b85811015610b1757604080838b031215610b7d578788fd5b610b856117f6565b610b8e84610a0d565b8152838701358782015285529385019390910190600101610b65565b600082601f830112610bba578081fd5b81356020610bca610a498361188d565b80838252828201915082860187848660051b8901011115610be9578586fd5b855b85811015610b1757813584529284019290840190600101610beb565b60006060808385031215610c19578182fd5b610c216117ce565b915082356001600160401b0380821115610c3a57600080fd5b818501915085601f830112610c4e57600080fd5b81356020610c5e610a498361188d565b82815281810190858301878502870184018b1015610c7b57600080fd5b600096505b84871015610cde5787818c031215610c9757600080fd5b610c9f6117ce565b610ca882610a0d565b815284820135858201526040808301358015158114610cc657600080fd5b90820152835260019690960195918301918701610c80565b5087525086810135945082851115610cf557600080fd5b610d0188868901610b24565b90860152506040850135925080831115610d1a57600080fd5b5050610d2884828501610a29565b60408301525092915050565b60006101408284031215610d46578081fd5b610d4e611818565b9050813581526020820135602082015260408201356040820152610d7460608301610a0d565b6060820152610d8560808301610f6c565b6080820152610d9660a08301610f6c565b60a0820152610da760c08301610f5a565b60c0820152610db860e08301610f5a565b60e0820152610100610dcb818401610a0d565b90820152610120610ddd838201610a0d565b9082015292915050565b6000610100808385031215610dfa578182fd5b604051908101906001600160401b0382118183101715610e1c57610e1c611904565b81604052809250833581526020840135602082015260408401356040820152610e4760608501610a0d565b6060820152610e5860808501610f6c565b6080820152610e6960a08501610f5a565b60a0820152610e7a60c08501610a0d565b60c0820152610e8b60e08501610a0d565b60e0820152505092915050565b600060808284031215610ea9578081fd5b610eb161183b565b90508135815260208083013581830152610ecd60408401610a0d565b604083015260608301356001600160401b0380821115610eec57600080fd5b818501915085601f830112610f0057600080fd5b813581811115610f1257610f12611904565b610f24601f8201601f1916850161185d565b91508082528684828501011115610f3a57600080fd5b808484018584013760008482840101525080606085015250505092915050565b803561ffff81168114610a2457600080fd5b803563ffffffff81168114610a2457600080fd5b600060208284031215610f91578081fd5b81516001600160e01b0319811681146101aa578182fd5b60008060006101808486031215610fbd578182fd5b610fc78585610d34565b92506101408401356001600160401b0380821115610fe3578384fd5b610fef87838801610c07565b9350610160860135915080821115611005578283fd5b5061101286828701610e98565b9150509250925092565b6000806000806101a08587031215611032578182fd5b61103c8686610d34565b93506101408501356001600160401b0380821115611058578384fd5b61106488838901610c07565b945061016087013591508082111561107a578384fd5b5061108787828801610e98565b9250506110976101808601610a0d565b905092959194509250565b60008061016083850312156110b5578182fd5b6110bf8484610d34565b91506101408301356001600160401b038111156110da578182fd5b6110e685828601610e98565b9150509250929050565b60008060006101808486031215611105578081fd5b61110f8585610d34565b92506101408401356001600160401b0381111561112a578182fd5b61113686828701610e98565b9250506111466101608501610a0d565b90509250925092565b60008060006101408486031215611164578081fd5b61116e8585610de7565b92506101008401356001600160401b038082111561118a578283fd5b61119687838801610c07565b9350610120860135915080821115611005578283fd5b60008060008061016085870312156111c2578182fd5b6111cc8686610de7565b93506101008501356001600160401b03808211156111e8578384fd5b6111f488838901610c07565b945061012087013591508082111561120a578384fd5b5061121787828801610e98565b9250506110976101408601610a0d565b600080610120838503121561123a578182fd5b6112448484610de7565b91506101008301356001600160401b038111156110da578182fd5b60008060006101408486031215611274578081fd5b61127e8585610de7565b92506101008401356001600160401b03811115611299578182fd5b6112a586828701610e98565b9250506111466101208501610a0d565b600080600080600060a086880312156112cc578283fd5b853594506112dc60208701610f6c565b9350604086013592506060860135915060808601356001600160401b03811115611304578182fd5b61131088828901610e98565b9150509295509295909350565b60008060008060008060c08789031215611335578384fd5b8635955061134560208801610f6c565b9450604087013593506060870135925060808701356001600160401b0381111561136d578182fd5b61137989828a01610e98565b92505061138860a08801610a0d565b90509295509295509295565b6000815180845260208085019450848260051b8601828601855b85811015610b17578383038952815180516001600160a01b03168452858101516060878601819052906113e382870182611462565b915050604080830151925085820381870152506114008183611462565b9a87019a94505050908401906001016113ae565b6000815180845260208085019450808401835b8381101561145757815180516001600160a01b031688528301518388015260409096019590820190600101611427565b509495945050505050565b6000815180845260208085019450808401835b8381101561145757815187529582019590820190600101611475565b60006001600160601b0319808d60601b1683528b60148401528a6034840152808a60601b166054840152886068840152808860601b1660888401525063ffffffff60e01b808760e01b16609c840152808660e01b1660a08401525061ffff60f01b8460f01b1660a483015261151560a683018460f01b6001600160f01b0319169052565b5060a8019a9950505050505050505050565b600082516115398184602087016118d4565b9190910192915050565b60008551611555818460208a016118d4565b855190830190611569818360208a016118d4565b60609590951b6001600160601b03191694019384525050601482015260340192915050565b600086516115a0818460208b016118d4565b8651908301906115b4818360208b016118d4565b86519101906115c7818360208a016118d4565b60609590951b6001600160601b0319169401938452505060148201526034019392505050565b87815263ffffffff60e01b8760e01b166020820152856024820152846044820152600084516116238160648501602089016118d4565b80830190506001600160601b03198560601b1660648201528360788201526098810191505098975050505050505050565b82815260406020820152600082518060408401526116798160608501602087016118d4565b601f01601f1916919091016060019392505050565b6020808252601e908201527f426f72726f776572205369676e61747572652068617320657870697265640000604082015260600190565b6020808252601c908201527f4c656e646572205369676e617475726520686173206578706972656400000000604082015260600190565b6020808252601490820152734c6f616e206973207a65726f206164647265737360601b604082015260600190565b60208082528251606083830181905281516080850181905260009392830191849160a08701905b8084101561179057845180516001600160a01b031683528681015187840152604090810151151590830152938501936001939093019290820190611751565b50848801519450601f199350838782030160408801526117b08186611414565b945050604087015191508286850301818701525061046c8382611394565b604051606081016001600160401b03811182821017156117f0576117f0611904565b60405290565b604080519081016001600160401b03811182821017156117f0576117f0611904565b60405161014081016001600160401b03811182821017156117f0576117f0611904565b604051608081016001600160401b03811182821017156117f0576117f0611904565b604051601f8201601f191681016001600160401b038111828210171561188557611885611904565b604052919050565b60006001600160401b038211156118a6576118a6611904565b5060051b60200190565b600082198211156118cf57634e487b7160e01b81526011600452602481fd5b500190565b60005b838110156118ef5781810151838201526020016118d7565b838111156118fe576000848401525b50505050565b634e487b7160e01b600052604160045260246000fdfea164736f6c6343000804000a
Deployed Bytecode
0x7360da568b88037d0735715819a37714d28bd5634730146080604052600436106100b35760003560e01c806387c0a5731161007b57806387c0a57314610127578063a819956e1461013a578063c42129211461014d578063d06ff74114610160578063eb2ac63f14610173578063fb7a322a1461018657600080fd5b80632eb68793146100b85780633ce5ed9f146100e05780634051a17a146100f3578063564b81ef146101065780636ab81ec014610114575b600080fd5b6100cb6100c6366004610fa8565b610199565b60405190151581526020015b60405180910390f35b6100cb6100ee36600461101c565b6101b1565b6100cb6101013660046110a2565b6102a9565b6040514681526020016100d7565b6100cb61012236600461125f565b6102b6565b6100cb61013536600461131d565b610376565b6100cb6101483660046111ac565b610476565b6100cb61015b3660046110f0565b6104e7565b6100cb61016e3660046112b5565b610558565b6100cb610181366004611227565b610568565b6100cb61019436600461114f565b610575565b60006101a7848484306101b1565b90505b9392505050565b600082602001514211156101e05760405162461bcd60e51b81526004016101d79061168e565b60405180910390fd5b6001600160a01b0382166102065760405162461bcd60e51b81526004016101d7906116fc565b60408301516001600160a01b0316610220575060006102a1565b600061022b86610583565b8560405160200161023c919061172a565b604051602081830303815290604052610254866105e8565b854660405160200161026a95949392919061158e565b60405160208183030381529060405280519060200120905061029d84604001516102938361062b565b866060015161067e565b9150505b949350505050565b60006101aa8383306104e7565b600082602001514211156102dc5760405162461bcd60e51b81526004016101d7906116c5565b6001600160a01b0382166103025760405162461bcd60e51b81526004016101d7906116fc565b60408301516001600160a01b031661031c575060006101aa565b6000610327856107d8565b610330856105e8565b84466040516020016103459493929190611543565b60405160208183030381529060405280519060200120905061036e84604001516102938361062b565b9150506101aa565b600082602001514211156103d85760405162461bcd60e51b815260206004820152602360248201527f52656e65676f74696174696f6e205369676e61747572652068617320657870696044820152621c995960ea1b60648201526084016101d7565b6001600160a01b0382166103fe5760405162461bcd60e51b81526004016101d7906116fc565b60408301516001600160a01b03166104185750600061046c565b600087878787610427886105e8565b874660405160200161043f97969594939291906115ed565b60405160208183030381529060405280519060200120905061046884604001516102938361062b565b9150505b9695505050505050565b6000826020015142111561049c5760405162461bcd60e51b81526004016101d7906116c5565b6001600160a01b0382166104c25760405162461bcd60e51b81526004016101d7906116fc565b60408301516001600160a01b03166104dc575060006102a1565b600061022b866107d8565b6000826020015142111561050d5760405162461bcd60e51b81526004016101d79061168e565b6001600160a01b0382166105335760405162461bcd60e51b81526004016101d7906116fc565b60408301516001600160a01b031661054d575060006101aa565b600061032785610583565b600061046c868686868630610376565b60006101aa8383306102b6565b60006101a784848430610476565b6060816101200151826000015183602001518460600151856040015186610100015187608001518860a001518960c001518a60e001516040516020016105d29a99989796959493929190611491565b6040516020818303038152906040529050919050565b60608160400151826000015183602001516040516020016105d29392919060609390931b6001600160601b03191683526014830191909152603482015260540190565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b600080600061068d8585610881565b909250905060008160048111156106b457634e487b7160e01b600052602160045260246000fd5b1480156106d25750856001600160a01b0316826001600160a01b0316145b156106e2576001925050506101aa565b600080876001600160a01b0316631626ba7e60e01b888860405160240161070a929190611654565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516107489190611527565b600060405180830381855afa9150503d8060008114610783576040519150601f19603f3d011682016040523d82523d6000602084013e610788565b606091505b509150915081801561079b575080516020145b80156107cc57508051630b135d3f60e11b906107c09083016020908101908401610f80565b6001600160e01b031916145b98975050505050505050565b60608160c0015182600001518360200151846060015185604001518660e0015187608001518860a001516040516020016105d2989796959493929190606098891b6001600160601b031990811682526014820198909852603481019690965293871b86166054860152606885019290925290941b909216608882015260e09290921b6001600160e01b031916609c83015260f01b6001600160f01b03191660a082015260a20190565b6000808251604114156108b85760208301516040840151606085015160001a6108ac878285856108f1565b945094505050506108ea565b8251604014156108e257602083015160408401516108d78683836109d4565b9350935050506108ea565b506000905060025b9250929050565b6000806fa2a8918ca85bafe22016d0b997e4df60600160ff1b0383111561091e57506000905060036109cb565b8460ff16601b1415801561093657508460ff16601c14155b1561094757506000905060046109cb565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561099b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166109c4576000600192509250506109cb565b9150600090505b94509492505050565b6000806001600160ff1b038316816109f160ff86901c601b6118b0565b90506109ff878288856108f1565b935093505050935093915050565b80356001600160a01b0381168114610a2457600080fd5b919050565b600082601f830112610a39578081fd5b81356020610a4e610a498361188d565b61185d565b80838252828201915082860187848660051b8901011115610a6d578586fd5b855b85811015610b175781356001600160401b0380821115610a8d578889fd5b908901906060828c03601f1901811315610aa557898afd5b610aad6117ce565b610ab8898501610a0d565b815260408085013584811115610acc578c8dfd5b610ada8f8c83890101610baa565b838c015250918401359183831115610af0578b8cfd5b610afe8e8b85880101610baa565b9082015287525050509284019290840190600101610a6f565b5090979650505050505050565b600082601f830112610b34578081fd5b81356020610b44610a498361188d565b80838252828201915082860187848660061b8901011115610b63578586fd5b855b85811015610b1757604080838b031215610b7d578788fd5b610b856117f6565b610b8e84610a0d565b8152838701358782015285529385019390910190600101610b65565b600082601f830112610bba578081fd5b81356020610bca610a498361188d565b80838252828201915082860187848660051b8901011115610be9578586fd5b855b85811015610b1757813584529284019290840190600101610beb565b60006060808385031215610c19578182fd5b610c216117ce565b915082356001600160401b0380821115610c3a57600080fd5b818501915085601f830112610c4e57600080fd5b81356020610c5e610a498361188d565b82815281810190858301878502870184018b1015610c7b57600080fd5b600096505b84871015610cde5787818c031215610c9757600080fd5b610c9f6117ce565b610ca882610a0d565b815284820135858201526040808301358015158114610cc657600080fd5b90820152835260019690960195918301918701610c80565b5087525086810135945082851115610cf557600080fd5b610d0188868901610b24565b90860152506040850135925080831115610d1a57600080fd5b5050610d2884828501610a29565b60408301525092915050565b60006101408284031215610d46578081fd5b610d4e611818565b9050813581526020820135602082015260408201356040820152610d7460608301610a0d565b6060820152610d8560808301610f6c565b6080820152610d9660a08301610f6c565b60a0820152610da760c08301610f5a565b60c0820152610db860e08301610f5a565b60e0820152610100610dcb818401610a0d565b90820152610120610ddd838201610a0d565b9082015292915050565b6000610100808385031215610dfa578182fd5b604051908101906001600160401b0382118183101715610e1c57610e1c611904565b81604052809250833581526020840135602082015260408401356040820152610e4760608501610a0d565b6060820152610e5860808501610f6c565b6080820152610e6960a08501610f5a565b60a0820152610e7a60c08501610a0d565b60c0820152610e8b60e08501610a0d565b60e0820152505092915050565b600060808284031215610ea9578081fd5b610eb161183b565b90508135815260208083013581830152610ecd60408401610a0d565b604083015260608301356001600160401b0380821115610eec57600080fd5b818501915085601f830112610f0057600080fd5b813581811115610f1257610f12611904565b610f24601f8201601f1916850161185d565b91508082528684828501011115610f3a57600080fd5b808484018584013760008482840101525080606085015250505092915050565b803561ffff81168114610a2457600080fd5b803563ffffffff81168114610a2457600080fd5b600060208284031215610f91578081fd5b81516001600160e01b0319811681146101aa578182fd5b60008060006101808486031215610fbd578182fd5b610fc78585610d34565b92506101408401356001600160401b0380821115610fe3578384fd5b610fef87838801610c07565b9350610160860135915080821115611005578283fd5b5061101286828701610e98565b9150509250925092565b6000806000806101a08587031215611032578182fd5b61103c8686610d34565b93506101408501356001600160401b0380821115611058578384fd5b61106488838901610c07565b945061016087013591508082111561107a578384fd5b5061108787828801610e98565b9250506110976101808601610a0d565b905092959194509250565b60008061016083850312156110b5578182fd5b6110bf8484610d34565b91506101408301356001600160401b038111156110da578182fd5b6110e685828601610e98565b9150509250929050565b60008060006101808486031215611105578081fd5b61110f8585610d34565b92506101408401356001600160401b0381111561112a578182fd5b61113686828701610e98565b9250506111466101608501610a0d565b90509250925092565b60008060006101408486031215611164578081fd5b61116e8585610de7565b92506101008401356001600160401b038082111561118a578283fd5b61119687838801610c07565b9350610120860135915080821115611005578283fd5b60008060008061016085870312156111c2578182fd5b6111cc8686610de7565b93506101008501356001600160401b03808211156111e8578384fd5b6111f488838901610c07565b945061012087013591508082111561120a578384fd5b5061121787828801610e98565b9250506110976101408601610a0d565b600080610120838503121561123a578182fd5b6112448484610de7565b91506101008301356001600160401b038111156110da578182fd5b60008060006101408486031215611274578081fd5b61127e8585610de7565b92506101008401356001600160401b03811115611299578182fd5b6112a586828701610e98565b9250506111466101208501610a0d565b600080600080600060a086880312156112cc578283fd5b853594506112dc60208701610f6c565b9350604086013592506060860135915060808601356001600160401b03811115611304578182fd5b61131088828901610e98565b9150509295509295909350565b60008060008060008060c08789031215611335578384fd5b8635955061134560208801610f6c565b9450604087013593506060870135925060808701356001600160401b0381111561136d578182fd5b61137989828a01610e98565b92505061138860a08801610a0d565b90509295509295509295565b6000815180845260208085019450848260051b8601828601855b85811015610b17578383038952815180516001600160a01b03168452858101516060878601819052906113e382870182611462565b915050604080830151925085820381870152506114008183611462565b9a87019a94505050908401906001016113ae565b6000815180845260208085019450808401835b8381101561145757815180516001600160a01b031688528301518388015260409096019590820190600101611427565b509495945050505050565b6000815180845260208085019450808401835b8381101561145757815187529582019590820190600101611475565b60006001600160601b0319808d60601b1683528b60148401528a6034840152808a60601b166054840152886068840152808860601b1660888401525063ffffffff60e01b808760e01b16609c840152808660e01b1660a08401525061ffff60f01b8460f01b1660a483015261151560a683018460f01b6001600160f01b0319169052565b5060a8019a9950505050505050505050565b600082516115398184602087016118d4565b9190910192915050565b60008551611555818460208a016118d4565b855190830190611569818360208a016118d4565b60609590951b6001600160601b03191694019384525050601482015260340192915050565b600086516115a0818460208b016118d4565b8651908301906115b4818360208b016118d4565b86519101906115c7818360208a016118d4565b60609590951b6001600160601b0319169401938452505060148201526034019392505050565b87815263ffffffff60e01b8760e01b166020820152856024820152846044820152600084516116238160648501602089016118d4565b80830190506001600160601b03198560601b1660648201528360788201526098810191505098975050505050505050565b82815260406020820152600082518060408401526116798160608501602087016118d4565b601f01601f1916919091016060019392505050565b6020808252601e908201527f426f72726f776572205369676e61747572652068617320657870697265640000604082015260600190565b6020808252601c908201527f4c656e646572205369676e617475726520686173206578706972656400000000604082015260600190565b6020808252601490820152734c6f616e206973207a65726f206164647265737360601b604082015260600190565b60208082528251606083830181905281516080850181905260009392830191849160a08701905b8084101561179057845180516001600160a01b031683528681015187840152604090810151151590830152938501936001939093019290820190611751565b50848801519450601f199350838782030160408801526117b08186611414565b945050604087015191508286850301818701525061046c8382611394565b604051606081016001600160401b03811182821017156117f0576117f0611904565b60405290565b604080519081016001600160401b03811182821017156117f0576117f0611904565b60405161014081016001600160401b03811182821017156117f0576117f0611904565b604051608081016001600160401b03811182821017156117f0576117f0611904565b604051601f8201601f191681016001600160401b038111828210171561188557611885611904565b604052919050565b60006001600160401b038211156118a6576118a6611904565b5060051b60200190565b600082198211156118cf57634e487b7160e01b81526011600452602481fd5b500190565b60005b838110156118ef5781810151838201526020016118d7565b838111156118fe576000848401525b50505050565b634e487b7160e01b600052604160045260246000fdfea164736f6c6343000804000a
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 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.