Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Advanced mode: Intended for advanced users or developers and will display all Internal Transactions including zero value transfers. Name tag integration is not available in advanced view.
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
||||
---|---|---|---|---|---|---|---|
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH | |||||
17422134 | 599 days ago | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
MapleLoan
Compiler Version
v0.8.7+commit.e28d00a7
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.7; import { IERC20 } from "../modules/erc20/contracts/interfaces/IERC20.sol"; import { ERC20Helper } from "../modules/erc20-helper/src/ERC20Helper.sol"; import { IMapleProxyFactory } from "../modules/maple-proxy-factory/contracts/interfaces/IMapleProxyFactory.sol"; import { MapleProxiedInternals } from "../modules/maple-proxy-factory/contracts/MapleProxiedInternals.sol"; import { IMapleLoan } from "./interfaces/IMapleLoan.sol"; import { IMapleLoanFeeManager } from "./interfaces/IMapleLoanFeeManager.sol"; import { IMapleGlobalsLike, ILenderLike, IMapleProxyFactoryLike } from "./interfaces/Interfaces.sol"; import { MapleLoanStorage } from "./MapleLoanStorage.sol"; /* ███╗ ███╗ █████╗ ██████╗ ██╗ ███████╗ ██╗ ██████╗ █████╗ ███╗ ██╗ ██╗ ██╗██╗ ██╗ ████╗ ████║██╔══██╗██╔══██╗██║ ██╔════╝ ██║ ██╔═══██╗██╔══██╗████╗ ██║ ██║ ██║██║ ██║ ██╔████╔██║███████║██████╔╝██║ █████╗ ██║ ██║ ██║███████║██╔██╗ ██║ ██║ ██║███████║ ██║╚██╔╝██║██╔══██║██╔═══╝ ██║ ██╔══╝ ██║ ██║ ██║██╔══██║██║╚██╗██║ ╚██╗ ██╔╝╚════██║ ██║ ╚═╝ ██║██║ ██║██║ ███████╗███████╗ ███████╗╚██████╔╝██║ ██║██║ ╚████║ ╚████╔╝ ██║ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚══════╝╚══════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═══╝ ╚═╝ */ /// @title MapleLoan implements a primitive loan with additional functionality, and is intended to be proxied. contract MapleLoan is IMapleLoan, MapleProxiedInternals, MapleLoanStorage { uint256 private constant SCALED_ONE = uint256(10 ** 18); modifier limitDrawableUse() { if (msg.sender == _borrower) { _; return; } uint256 drawableFundsBeforePayment = _drawableFunds; _; // Either the caller is the borrower or `_drawableFunds` has not decreased. require(_drawableFunds >= drawableFundsBeforePayment, "ML:CANNOT_USE_DRAWABLE"); } // NOTE: The following functions already check for paused state in the poolManager/loanManager, therefore no need to check here. // * acceptNewTerms // * fundLoan // * impairLoan // * removeLoanImpairment // * repossess // * setPendingLender -> Not implemented modifier whenProtocolNotPaused() { require(!IMapleGlobalsLike(globals()).protocolPaused(), "L:PROTOCOL_PAUSED"); _; } /*******************************************************************************************************************************/ /*** Administrative Functions ***/ /*******************************************************************************************************************************/ function migrate(address migrator_, bytes calldata arguments_) external override { require(msg.sender == _factory(), "ML:M:NOT_FACTORY"); require(_migrate(migrator_, arguments_), "ML:M:FAILED"); } function setImplementation(address newImplementation_) external override { require(msg.sender == _factory(), "ML:SI:NOT_FACTORY"); require(_setImplementation(newImplementation_), "ML:SI:FAILED"); } function upgrade(uint256 toVersion_, bytes calldata arguments_) external override whenProtocolNotPaused { require(msg.sender == IMapleGlobalsLike(globals()).securityAdmin(), "ML:U:NOT_SECURITY_ADMIN"); emit Upgraded(toVersion_, arguments_); IMapleProxyFactory(_factory()).upgradeInstance(toVersion_, arguments_); } /******************************************************************************************************************************/ /*** Borrow Functions ***/ /******************************************************************************************************************************/ function acceptBorrower() external override whenProtocolNotPaused { require(msg.sender == _pendingBorrower, "ML:AB:NOT_PENDING_BORROWER"); _pendingBorrower = address(0); emit BorrowerAccepted(_borrower = msg.sender); } function closeLoan(uint256 amount_) external override limitDrawableUse whenProtocolNotPaused returns (uint256 principal_, uint256 interest_, uint256 fees_) { // The amount specified is an optional amount to be transferred from the caller, as a convenience for EOAs. // NOTE: FUNDS SHOULD NOT BE TRANSFERRED TO THIS CONTRACT NON-ATOMICALLY. IF THEY ARE, THE BALANCE MAY BE STOLEN USING `skim`. require(amount_ == uint256(0) || ERC20Helper.transferFrom(_fundsAsset, msg.sender, address(this), amount_), "ML:CL:TRANSFER_FROM_FAILED"); uint256 paymentDueDate_ = _nextPaymentDueDate; require(block.timestamp <= paymentDueDate_, "ML:CL:PAYMENT_IS_LATE"); _handleImpairment(); ( principal_, interest_, ) = getClosingPaymentBreakdown(); _refinanceInterest = uint256(0); uint256 principalAndInterest = principal_ + interest_; // The drawable funds are increased by the extra funds in the contract, minus the total needed for payment. // NOTE: This line will revert if not enough funds were added for the full payment amount. _drawableFunds = (_drawableFunds + getUnaccountedAmount(_fundsAsset)) - principalAndInterest; fees_ = _handleServiceFeePayment(_paymentsRemaining); _clearLoanAccounting(); emit LoanClosed(principal_, interest_, fees_); require(ERC20Helper.transfer(_fundsAsset, _lender, principalAndInterest), "ML:MP:TRANSFER_FAILED"); ILenderLike(_lender).claim(principal_, interest_, paymentDueDate_, 0); emit FundsClaimed(principalAndInterest, _lender); } function drawdownFunds(uint256 amount_, address destination_) external override whenProtocolNotPaused returns (uint256 collateralPosted_) { require(msg.sender == _borrower, "ML:DF:NOT_BORROWER"); emit FundsDrawnDown(amount_, destination_); // Post additional collateral required to facilitate this drawdown, if needed. uint256 additionalCollateralRequired = getAdditionalCollateralRequiredFor(amount_); if (additionalCollateralRequired > uint256(0)) { // Determine collateral currently unaccounted for. uint256 unaccountedCollateral = getUnaccountedAmount(_collateralAsset); // Post required collateral, specifying then amount lacking as the optional amount to be transferred from. collateralPosted_ = postCollateral( additionalCollateralRequired > unaccountedCollateral ? additionalCollateralRequired - unaccountedCollateral : uint256(0) ); } _drawableFunds -= amount_; require(ERC20Helper.transfer(_fundsAsset, destination_, amount_), "ML:DF:TRANSFER_FAILED"); require(_isCollateralMaintained(), "ML:DF:INSUFFICIENT_COLLATERAL"); } function makePayment(uint256 amount_) external override limitDrawableUse whenProtocolNotPaused returns (uint256 principal_, uint256 interest_, uint256 fees_) { // The amount specified is an optional amount to be transfer from the caller, as a convenience for EOAs. // NOTE: FUNDS SHOULD NOT BE TRANSFERRED TO THIS CONTRACT NON-ATOMICALLY. IF THEY ARE, THE BALANCE MAY BE STOLEN USING `skim`. require(amount_ == uint256(0) || ERC20Helper.transferFrom(_fundsAsset, msg.sender, address(this), amount_), "ML:MP:TRANSFER_FROM_FAILED"); _handleImpairment(); ( principal_, interest_, ) = getNextPaymentBreakdown(); _refinanceInterest = uint256(0); uint256 principalAndInterest = principal_ + interest_; // The drawable funds are increased by the extra funds in the contract, minus the total needed for payment. // NOTE: This line will revert if not enough funds were added for the full payment amount. _drawableFunds = (_drawableFunds + getUnaccountedAmount(_fundsAsset)) - principalAndInterest; fees_ = _handleServiceFeePayment(1); uint256 paymentsRemaining_ = _paymentsRemaining; uint256 previousPaymentDueDate_ = _nextPaymentDueDate; uint256 nextPaymentDueDate_; if (paymentsRemaining_ == uint256(1)) { _clearLoanAccounting(); // Assumes `getNextPaymentBreakdown` returns a `principal_` that is `_principal`. } else { _nextPaymentDueDate = nextPaymentDueDate_ = previousPaymentDueDate_ + _paymentInterval; _principal -= principal_; _paymentsRemaining = paymentsRemaining_ - uint256(1); } emit PaymentMade(principal_, interest_, fees_); require(ERC20Helper.transfer(_fundsAsset, _lender, principalAndInterest), "ML:MP:TRANSFER_FAILED"); ILenderLike(_lender).claim(principal_, interest_, previousPaymentDueDate_, nextPaymentDueDate_); emit FundsClaimed(principalAndInterest, _lender); } function postCollateral(uint256 amount_) public override whenProtocolNotPaused returns (uint256 collateralPosted_) { // The amount specified is an optional amount to be transfer from the caller, as a convenience for EOAs. // NOTE: FUNDS SHOULD NOT BE TRANSFERRED TO THIS CONTRACT NON-ATOMICALLY. IF THEY ARE, THE BALANCE MAY BE STOLEN USING `skim`. require( amount_ == uint256(0) || ERC20Helper.transferFrom(_collateralAsset, msg.sender, address(this), amount_), "ML:PC:TRANSFER_FROM_FAILED" ); _collateral += (collateralPosted_ = getUnaccountedAmount(_collateralAsset)); emit CollateralPosted(collateralPosted_); } function proposeNewTerms(address refinancer_, uint256 deadline_, bytes[] calldata calls_) external override whenProtocolNotPaused returns (bytes32 refinanceCommitment_) { require(msg.sender == _borrower, "ML:PNT:NOT_BORROWER"); require(deadline_ >= block.timestamp, "ML:PNT:INVALID_DEADLINE"); emit NewTermsProposed( refinanceCommitment_ = _refinanceCommitment = calls_.length > uint256(0) ? _getRefinanceCommitment(refinancer_, deadline_, calls_) : bytes32(0), refinancer_, deadline_, calls_ ); } function removeCollateral(uint256 amount_, address destination_) external override whenProtocolNotPaused { require(msg.sender == _borrower, "ML:RC:NOT_BORROWER"); emit CollateralRemoved(amount_, destination_); _collateral -= amount_; require(ERC20Helper.transfer(_collateralAsset, destination_, amount_), "ML:RC:TRANSFER_FAILED"); require(_isCollateralMaintained(), "ML:RC:INSUFFICIENT_COLLATERAL"); } function returnFunds(uint256 amount_) external override whenProtocolNotPaused returns (uint256 fundsReturned_) { // The amount specified is an optional amount to be transfer from the caller, as a convenience for EOAs. // NOTE: FUNDS SHOULD NOT BE TRANSFERRED TO THIS CONTRACT NON-ATOMICALLY. IF THEY ARE, THE BALANCE MAY BE STOLEN USING `skim`. require(amount_ == uint256(0) || ERC20Helper.transferFrom(_fundsAsset, msg.sender, address(this), amount_), "ML:RF:TRANSFER_FROM_FAILED"); _drawableFunds += (fundsReturned_ = getUnaccountedAmount(_fundsAsset)); emit FundsReturned(fundsReturned_); } function setPendingBorrower(address pendingBorrower_) external override whenProtocolNotPaused { require(msg.sender == _borrower, "ML:SPB:NOT_BORROWER"); require(IMapleGlobalsLike(globals()).isBorrower(pendingBorrower_), "ML:SPB:INVALID_BORROWER"); emit PendingBorrowerSet(_pendingBorrower = pendingBorrower_); } /******************************************************************************************************************************/ /*** Lend Functions ***/ /******************************************************************************************************************************/ function acceptLender() external override whenProtocolNotPaused { require(msg.sender == _pendingLender, "ML:AL:NOT_PENDING_LENDER"); _pendingLender = address(0); emit LenderAccepted(_lender = msg.sender); } function acceptNewTerms(address refinancer_, uint256 deadline_, bytes[] calldata calls_) external override returns (bytes32 refinanceCommitment_) { require(msg.sender == _lender, "ML:ANT:NOT_LENDER"); // NOTE: A zero refinancer address and/or empty calls array will never (probabilistically) match a refinance commitment in storage. require( _refinanceCommitment == (refinanceCommitment_ = _getRefinanceCommitment(refinancer_, deadline_, calls_)), "ML:ANT:COMMITMENT_MISMATCH" ); require(refinancer_.code.length != uint256(0), "ML:ANT:INVALID_REFINANCER"); require(block.timestamp <= deadline_, "ML:ANT:EXPIRED_COMMITMENT"); uint256 paymentInterval_ = _paymentInterval; uint256 nextPaymentDueDate_ = _nextPaymentDueDate; uint256 previousPrincipalRequested = _principalRequested; uint256 timeSinceLastDueDate_ = block.timestamp + paymentInterval_ < nextPaymentDueDate_ ? 0 : block.timestamp - (nextPaymentDueDate_ - paymentInterval_); // Not ideal for checks-effects-interactions, but the feeManager is a trusted contract and it's needed to save the fee before refinance. IMapleLoanFeeManager feeManager_ = IMapleLoanFeeManager(_feeManager); feeManager_.updateRefinanceServiceFees(previousPrincipalRequested, timeSinceLastDueDate_); // Get the amount of interest owed since the last payment due date, as well as the time since the last due date uint256 proRataInterest = getRefinanceInterest(block.timestamp); // In case there is still a refinance interest, just increment it instead of setting it. _refinanceInterest += proRataInterest; // Clear refinance commitment to prevent implications of re-acceptance of another call to `_acceptNewTerms`. _refinanceCommitment = bytes32(0); for (uint256 i; i < calls_.length;) { ( bool success, ) = refinancer_.delegatecall(calls_[i]); require(success, "ML:ANT:FAILED"); unchecked { ++i; } } emit NewTermsAccepted(refinanceCommitment_, refinancer_, deadline_, calls_); address fundsAsset_ = _fundsAsset; uint256 principalRequested_ = _principalRequested; paymentInterval_ = _paymentInterval; // Increment the due date to be one full payment interval from now, to restart the payment schedule with new terms. // NOTE: `_paymentInterval` here is possibly newly set via the above delegate calls, so cache it. _nextPaymentDueDate = block.timestamp + paymentInterval_; _handleImpairment(); // Update Platform Fees and pay originations. feeManager_.updatePlatformServiceFee(principalRequested_, paymentInterval_); _drawableFunds -= feeManager_.payOriginationFees(fundsAsset_, principalRequested_); // Ensure that collateral is maintained after changes made. require(_isCollateralMaintained(), "ML:ANT:INSUFFICIENT_COLLATERAL"); require(getUnaccountedAmount(fundsAsset_) == uint256(0), "ML:ANT:UNEXPECTED_FUNDS"); } function fundLoan(address lender_) external override returns (uint256 fundsLent_) { require((_lender = lender_) != address(0), "ML:FL:INVALID_LENDER"); address loanManagerFactory_ = ILenderLike(lender_).factory(); require(IMapleGlobalsLike(globals()).isFactory("LOAN_MANAGER", loanManagerFactory_), "ML:FL:INVALID_FACTORY"); require(IMapleProxyFactoryLike(loanManagerFactory_).isInstance(lender_), "ML:FL:INVALID_INSTANCE"); // Can only fund loan if there are payments remaining (as defined by the initialization) and no payment is due yet (as set by a funding). require((_nextPaymentDueDate == uint256(0)) && (_paymentsRemaining != uint256(0)), "ML:FL:LOAN_ACTIVE"); address fundsAsset_ = _fundsAsset; uint256 paymentInterval_ = _paymentInterval; uint256 principalRequested_ = _principalRequested; require(ERC20Helper.approve(fundsAsset_, _feeManager, type(uint256).max), "ML:FL:APPROVE_FAIL"); // Saves the platform service fee rate for future payments. IMapleLoanFeeManager(_feeManager).updatePlatformServiceFee(principalRequested_, paymentInterval_); uint256 originationFees_ = IMapleLoanFeeManager(_feeManager).payOriginationFees(fundsAsset_, principalRequested_); _drawableFunds = principalRequested_ - originationFees_; require(getUnaccountedAmount(fundsAsset_) == uint256(0), "ML:FL:UNEXPECTED_FUNDS"); emit Funded( lender_, fundsLent_ = _principal = principalRequested_, _nextPaymentDueDate = block.timestamp + paymentInterval_ ); } function removeLoanImpairment() external override { uint256 originalNextPaymentDueDate_ = _originalNextPaymentDueDate; require(msg.sender == _lender, "ML:RLI:NOT_LENDER"); require(originalNextPaymentDueDate_ != 0, "ML:RLI:NOT_IMPAIRED"); require(block.timestamp <= originalNextPaymentDueDate_, "ML:RLI:PAST_DATE"); _nextPaymentDueDate = originalNextPaymentDueDate_; delete _originalNextPaymentDueDate; emit NextPaymentDueDateRestored(originalNextPaymentDueDate_); } function repossess(address destination_) external override returns (uint256 collateralRepossessed_, uint256 fundsRepossessed_) { require(msg.sender == _lender, "ML:R:NOT_LENDER"); uint256 nextPaymentDueDate_ = _nextPaymentDueDate; require( nextPaymentDueDate_ != uint256(0) && (block.timestamp > nextPaymentDueDate_ + _gracePeriod), "ML:R:NOT_IN_DEFAULT" ); _clearLoanAccounting(); // Uniquely in `_repossess`, stop accounting for all funds so that they can be swept. _collateral = uint256(0); _drawableFunds = uint256(0); address collateralAsset_ = _collateralAsset; // Either there is no collateral to repossess, or the transfer of the collateral succeeds. require( (collateralRepossessed_ = getUnaccountedAmount(collateralAsset_)) == uint256(0) || ERC20Helper.transfer(collateralAsset_, destination_, collateralRepossessed_), "ML:R:C_TRANSFER_FAILED" ); address fundsAsset_ = _fundsAsset; // Either there are no funds to repossess, or the transfer of the funds succeeds. require( (fundsRepossessed_ = getUnaccountedAmount(fundsAsset_)) == uint256(0) || ERC20Helper.transfer(fundsAsset_, destination_, fundsRepossessed_), "ML:R:F_TRANSFER_FAILED" ); emit Repossessed(collateralRepossessed_, fundsRepossessed_, destination_); } function setPendingLender(address pendingLender_) external override { require(msg.sender == _lender, "ML:SPL:NOT_LENDER"); emit PendingLenderSet(_pendingLender = pendingLender_); } function impairLoan() external override { uint256 originalNextPaymentDueDate_ = _nextPaymentDueDate; require(msg.sender == _lender, "ML:IL:NOT_LENDER"); // If the loan is late, do not change the payment due date. uint256 newPaymentDueDate_ = block.timestamp > originalNextPaymentDueDate_ ? originalNextPaymentDueDate_ : block.timestamp; emit LoanImpaired(newPaymentDueDate_); _nextPaymentDueDate = newPaymentDueDate_; _originalNextPaymentDueDate = originalNextPaymentDueDate_; // Store the existing payment due date to enable reversion. } /******************************************************************************************************************************/ /*** Miscellaneous Functions ***/ /******************************************************************************************************************************/ function rejectNewTerms(address refinancer_, uint256 deadline_, bytes[] calldata calls_) external override whenProtocolNotPaused returns (bytes32 refinanceCommitment_) { require((msg.sender == _borrower) || (msg.sender == _lender), "ML:RNT:NO_AUTH"); require( _refinanceCommitment == (refinanceCommitment_ = _getRefinanceCommitment(refinancer_, deadline_, calls_)), "ML:RNT:COMMITMENT_MISMATCH" ); _refinanceCommitment = bytes32(0); emit NewTermsRejected(refinanceCommitment_, refinancer_, deadline_, calls_); } function skim(address token_, address destination_) external override whenProtocolNotPaused returns (uint256 skimmed_) { emit Skimmed(token_, skimmed_ = getUnaccountedAmount(token_), destination_); require(ERC20Helper.transfer(token_, destination_, skimmed_), "ML:S:TRANSFER_FAILED"); } /******************************************************************************************************************************/ /*** View Functions ***/ /******************************************************************************************************************************/ function getAdditionalCollateralRequiredFor(uint256 drawdown_) public view override returns (uint256 collateral_) { // Determine the collateral needed in the contract for a reduced drawable funds amount. uint256 collateralNeeded = _getCollateralRequiredFor(_principal, _drawableFunds - drawdown_, _principalRequested, _collateralRequired); uint256 currentCollateral = _collateral; return collateralNeeded > currentCollateral ? collateralNeeded - currentCollateral : uint256(0); } function getClosingPaymentBreakdown() public view override returns (uint256 principal_, uint256 interest_, uint256 fees_) { ( uint256 delegateServiceFee_, uint256 delegateRefinanceFee_, uint256 platformServiceFee_, uint256 platformRefinanceFee_ ) = IMapleLoanFeeManager(_feeManager).getServiceFeeBreakdown(address(this), _paymentsRemaining); fees_ = delegateServiceFee_ + platformServiceFee_ + delegateRefinanceFee_ + platformRefinanceFee_; // Compute interest and include any uncaptured interest from refinance. interest_ = (((principal_ = _principal) * _closingRate) / SCALED_ONE) + _refinanceInterest; } function getNextPaymentDetailedBreakdown() public view override returns ( uint256 principal_, uint256[3] memory interest_, uint256[2] memory fees_ ) { ( principal_, interest_, fees_ ) = _getPaymentBreakdown( block.timestamp, _nextPaymentDueDate, _paymentInterval, _principal, _endingPrincipal, _paymentsRemaining, _interestRate, _lateFeeRate, _lateInterestPremium ); } function getNextPaymentBreakdown() public view override returns (uint256 principal_, uint256 interest_, uint256 fees_) { uint256[3] memory interestArray_; uint256[2] memory feesArray_; ( principal_, interestArray_, feesArray_ ) = _getPaymentBreakdown( block.timestamp, _nextPaymentDueDate, _paymentInterval, _principal, _endingPrincipal, _paymentsRemaining, _interestRate, _lateFeeRate, _lateInterestPremium ); interest_ = interestArray_[0] + interestArray_[1] + interestArray_[2]; fees_ = feesArray_[0] + feesArray_[1]; } function getRefinanceInterest(uint256 timestamp_) public view override returns (uint256 proRataInterest_) { proRataInterest_ = _getRefinanceInterest( timestamp_, _paymentInterval, _principal, _endingPrincipal, _interestRate, _paymentsRemaining, _nextPaymentDueDate, _lateFeeRate, _lateInterestPremium ); } function getUnaccountedAmount(address asset_) public view override returns (uint256 unaccountedAmount_) { return IERC20(asset_).balanceOf(address(this)) - (asset_ == _collateralAsset ? _collateral : uint256(0)) // `_collateral` is `_collateralAsset` accounted for. - (asset_ == _fundsAsset ? _drawableFunds : uint256(0)); // `_drawableFunds` is `_fundsAsset` accounted for. } /******************************************************************************************************************************/ /*** State View Functions ***/ /******************************************************************************************************************************/ function borrower() external view override returns (address borrower_) { return _borrower; } function closingRate() external view override returns (uint256 closingRate_) { return _closingRate; } function collateral() external view override returns (uint256 collateral_) { return _collateral; } function collateralAsset() external view override returns (address collateralAsset_) { return _collateralAsset; } function collateralRequired() external view override returns (uint256 collateralRequired_) { return _collateralRequired; } function drawableFunds() external view override returns (uint256 drawableFunds_) { return _drawableFunds; } function endingPrincipal() external view override returns (uint256 endingPrincipal_) { return _endingPrincipal; } function excessCollateral() external view override returns (uint256 excessCollateral_) { uint256 collateralNeeded = _getCollateralRequiredFor(_principal, _drawableFunds, _principalRequested, _collateralRequired); uint256 currentCollateral = _collateral; return currentCollateral > collateralNeeded ? currentCollateral - collateralNeeded : uint256(0); } function factory() external view override returns (address factory_) { return _factory(); } function feeManager() external view override returns (address feeManager_) { return _feeManager; } function fundsAsset() external view override returns (address fundsAsset_) { return _fundsAsset; } function globals() public view override returns (address globals_) { globals_ = IMapleProxyFactoryLike(_factory()).mapleGlobals(); } function governor() public view override returns (address governor_) { governor_ = IMapleGlobalsLike(globals()).governor(); } function gracePeriod() external view override returns (uint256 gracePeriod_) { return _gracePeriod; } function implementation() external view override returns (address implementation_) { return _implementation(); } function interestRate() external view override returns (uint256 interestRate_) { return _interestRate; } function lateFeeRate() external view override returns (uint256 lateFeeRate_) { return _lateFeeRate; } function lateInterestPremium() external view override returns (uint256 lateInterestPremium_) { return _lateInterestPremium; } function lender() external view override returns (address lender_) { return _lender; } function nextPaymentDueDate() external view override returns (uint256 nextPaymentDueDate_) { return _nextPaymentDueDate; } function originalNextPaymentDueDate() external view override returns (uint256 originalNextPaymentDueDate_) { return _originalNextPaymentDueDate; } function paymentInterval() external view override returns (uint256 paymentInterval_) { return _paymentInterval; } function paymentsRemaining() external view override returns (uint256 paymentsRemaining_) { return _paymentsRemaining; } function pendingBorrower() external view override returns (address pendingBorrower_) { return _pendingBorrower; } function pendingLender() external view override returns (address pendingLender_) { return _pendingLender; } function principal() external view override returns (uint256 principal_) { return _principal; } function principalRequested() external view override returns (uint256 principalRequested_) { return _principalRequested; } function refinanceCommitment() external view override returns (bytes32 refinanceCommitment_) { return _refinanceCommitment; } function refinanceInterest() external view override returns (uint256 refinanceInterest_) { return _refinanceInterest; } function isImpaired() public view override returns (bool isImpaired_) { return _originalNextPaymentDueDate != uint256(0); } /******************************************************************************************************************************/ /*** Internal General Functions ***/ /******************************************************************************************************************************/ /// @dev Clears all state variables to end a loan, but keep borrower and lender withdrawal functionality intact. function _clearLoanAccounting() internal { _gracePeriod = uint256(0); _paymentInterval = uint256(0); _interestRate = uint256(0); _closingRate = uint256(0); _lateFeeRate = uint256(0); _lateInterestPremium = uint256(0); _endingPrincipal = uint256(0); _nextPaymentDueDate = uint256(0); _paymentsRemaining = uint256(0); _principal = uint256(0); _originalNextPaymentDueDate = uint256(0); } /******************************************************************************************************************************/ /*** Internal View Functions ***/ /******************************************************************************************************************************/ /// @dev Returns whether the amount of collateral posted is commensurate with the amount of drawn down (outstanding) principal. function _isCollateralMaintained() internal view returns (bool isMaintained_) { return _collateral >= _getCollateralRequiredFor(_principal, _drawableFunds, _principalRequested, _collateralRequired); } /******************************************************************************************************************************/ /*** Internal Pure Functions ***/ /******************************************************************************************************************************/ /// @dev Returns the total collateral to be posted for some drawn down (outstanding) principal and overall collateral ratio requirement. function _getCollateralRequiredFor( uint256 principal_, uint256 drawableFunds_, uint256 principalRequested_, uint256 collateralRequired_ ) internal pure returns (uint256 collateral_) { // Where (collateral / outstandingPrincipal) should be greater or equal to (collateralRequired / principalRequested). // NOTE: principalRequested_ cannot be 0, which is reasonable, since it means this was never a loan. return principal_ <= drawableFunds_ ? uint256(0) : (collateralRequired_ * (principal_ - drawableFunds_) + principalRequested_ - 1) / principalRequested_; } /// @dev Returns principal and interest portions of a payment instalment, given generic, stateless loan parameters. function _getInstallment(uint256 principal_, uint256 endingPrincipal_, uint256 interestRate_, uint256 paymentInterval_, uint256 totalPayments_) internal pure returns (uint256 principalAmount_, uint256 interestAmount_) { /*************************************************************************************************\ * | * * A = installment amount | / \ / R \ * * P = principal remaining | | / \ | | ----------------------- | * * R = interest rate | A = | | P * ( 1 + R ) ^ N | - E | * | / \ | * * N = payments remaining | | \ / | | | ( 1 + R ) ^ N | - 1 | * * E = ending principal target | \ / \ \ / / * * | * * |---------------------------------------------------------------- * * * * - Where R is `periodicRate` * * - Where (1 + R) ^ N is `raisedRate` * * - Both of these rates are scaled by 1e18 (e.g., 12% => 0.12 * 10 ** 18) * \*************************************************************************************************/ uint256 periodicRate = _getPeriodicInterestRate(interestRate_, paymentInterval_); uint256 raisedRate = _scaledExponent(SCALED_ONE + periodicRate, totalPayments_, SCALED_ONE); // NOTE: If a lack of precision in `_scaledExponent` results in a `raisedRate` smaller than one, assume it to be one and simplify the equation. if (raisedRate <= SCALED_ONE) return ((principal_ - endingPrincipal_) / totalPayments_, uint256(0)); uint256 total = ((((principal_ * raisedRate) / SCALED_ONE) - endingPrincipal_) * periodicRate) / (raisedRate - SCALED_ONE); interestAmount_ = _getInterest(principal_, interestRate_, paymentInterval_); principalAmount_ = total >= interestAmount_ ? total - interestAmount_ : uint256(0); } /// @dev Returns an amount by applying an annualized and scaled interest rate, to a principal, over an interval of time. function _getInterest(uint256 principal_, uint256 interestRate_, uint256 interval_) internal pure returns (uint256 interest_) { return (principal_ * _getPeriodicInterestRate(interestRate_, interval_)) / SCALED_ONE; } /// @dev Returns total principal and interest portion of a number of payments, given generic, stateless loan parameters and loan state. function _getPaymentBreakdown( uint256 currentTime_, uint256 nextPaymentDueDate_, uint256 paymentInterval_, uint256 principal_, uint256 endingPrincipal_, uint256 paymentsRemaining_, uint256 interestRate_, uint256 lateFeeRate_, uint256 lateInterestPremium_ ) internal view returns ( uint256 principalAmount_, uint256[3] memory interest_, uint256[2] memory fees_ ) { ( principalAmount_, interest_[0] ) = _getInstallment( principal_, endingPrincipal_, interestRate_, paymentInterval_, paymentsRemaining_ ); principalAmount_ = paymentsRemaining_ == uint256(1) ? principal_ : principalAmount_; interest_[1] = _getLateInterest( currentTime_, principal_, interestRate_, nextPaymentDueDate_, lateFeeRate_, lateInterestPremium_ ); interest_[2] = _refinanceInterest; ( uint256 delegateServiceFee_, uint256 delegateRefinanceFee_, uint256 platformServiceFee_, uint256 platformRefinanceFee_ ) = IMapleLoanFeeManager(_feeManager).getServiceFeeBreakdown(address(this), 1); fees_[0] = delegateServiceFee_ + delegateRefinanceFee_; fees_[1] = platformServiceFee_ + platformRefinanceFee_; } function _getRefinanceInterest( uint256 currentTime_, uint256 paymentInterval_, uint256 principal_, uint256 endingPrincipal_, uint256 interestRate_, uint256 paymentsRemaining_, uint256 nextPaymentDueDate_, uint256 lateFeeRate_, uint256 lateInterestPremium_ ) internal pure returns (uint256 refinanceInterest_) { // If the user has made an early payment, there is no refinance interest owed. if (currentTime_ + paymentInterval_ < nextPaymentDueDate_) return 0; uint256 timeSinceLastPaymentDueDate_ = currentTime_ - (nextPaymentDueDate_ - paymentInterval_); ( , refinanceInterest_ ) = _getInstallment( principal_, endingPrincipal_, interestRate_, timeSinceLastPaymentDueDate_, paymentsRemaining_ ); refinanceInterest_ += _getLateInterest( currentTime_, principal_, interestRate_, nextPaymentDueDate_, lateFeeRate_, lateInterestPremium_ ); } function _getLateInterest( uint256 currentTime_, uint256 principal_, uint256 interestRate_, uint256 nextPaymentDueDate_, uint256 lateFeeRate_, uint256 lateInterestPremium_ ) internal pure returns (uint256 lateInterest_) { if (currentTime_ <= nextPaymentDueDate_) return 0; // Calculates the number of full days late in seconds (will always be multiples of 86,400). // Rounds up and is inclusive so that if a payment is 1s late or 24h0m0s late it is 1 full day late. // 24h0m1s late would be two full days late. // ((86400n - 0n + (86400n - 1n)) / 86400n) * 86400n = 86400n // ((86401n - 0n + (86400n - 1n)) / 86400n) * 86400n = 172800n uint256 fullDaysLate = ((currentTime_ - nextPaymentDueDate_ + (1 days - 1)) / 1 days) * 1 days; lateInterest_ += _getInterest(principal_, interestRate_ + lateInterestPremium_, fullDaysLate); lateInterest_ += (lateFeeRate_ * principal_) / SCALED_ONE; } /// @dev Returns the interest rate over an interval, given an annualized interest rate. function _getPeriodicInterestRate(uint256 interestRate_, uint256 interval_) internal pure returns (uint256 periodicInterestRate_) { return (interestRate_ * interval_) / uint256(365 days); } /// @dev Returns refinance commitment given refinance parameters. function _getRefinanceCommitment(address refinancer_, uint256 deadline_, bytes[] calldata calls_) internal pure returns (bytes32 refinanceCommitment_) { return keccak256(abi.encode(refinancer_, deadline_, calls_)); } function _handleServiceFeePayment(uint256 numberOfPayments_) internal returns (uint256 fees_) { uint256 balanceBeforeServiceFees_ = IERC20(_fundsAsset).balanceOf(address(this)); IMapleLoanFeeManager(_feeManager).payServiceFees(_fundsAsset, numberOfPayments_); uint256 balanceAfterServiceFees_ = IERC20(_fundsAsset).balanceOf(address(this)); if (balanceBeforeServiceFees_ > balanceAfterServiceFees_) { _drawableFunds -= (fees_ = balanceBeforeServiceFees_ - balanceAfterServiceFees_); } else { _drawableFunds += balanceAfterServiceFees_ - balanceBeforeServiceFees_; } } function _handleImpairment() internal { if (!isImpaired()) return; _originalNextPaymentDueDate = uint256(0); } /** * @dev Returns exponentiation of a scaled base value. * * Walk through example: * LINE | base_ | exponent_ | one_ | result_ * | 3_00 | 18 | 1_00 | 0_00 * A | 3_00 | 18 | 1_00 | 1_00 * B | 3_00 | 9 | 1_00 | 1_00 * C | 9_00 | 9 | 1_00 | 1_00 * D | 9_00 | 9 | 1_00 | 9_00 * B | 9_00 | 4 | 1_00 | 9_00 * C | 81_00 | 4 | 1_00 | 9_00 * B | 81_00 | 2 | 1_00 | 9_00 * C | 6_561_00 | 2 | 1_00 | 9_00 * B | 6_561_00 | 1 | 1_00 | 9_00 * C | 43_046_721_00 | 1 | 1_00 | 9_00 * D | 43_046_721_00 | 1 | 1_00 | 387_420_489_00 * B | 43_046_721_00 | 0 | 1_00 | 387_420_489_00 * * Another implementation of this algorithm can be found in Dapphub's DSMath contract: * https://github.com/dapphub/ds-math/blob/ce67c0fa9f8262ecd3d76b9e4c026cda6045e96c/src/math.sol#L77 */ function _scaledExponent(uint256 base_, uint256 exponent_, uint256 one_) internal pure returns (uint256 result_) { // If exponent_ is odd, set result_ to base_, else set to one_. result_ = exponent_ & uint256(1) != uint256(0) ? base_ : one_; // A // Divide exponent_ by 2 (overwriting itself) and proceed if not zero. while ((exponent_ >>= uint256(1)) != uint256(0)) { // B base_ = (base_ * base_) / one_; // C // If exponent_ is even, go back to top. if (exponent_ & uint256(1) == uint256(0)) continue; // If exponent_ is odd, multiply result_ is multiplied by base_. result_ = (result_ * base_) / one_; // D } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.7; /// @title MapleLoanStorage defines the storage layout of MapleLoan. abstract contract MapleLoanStorage { // Roles address internal _borrower; // The address of the borrower. address internal _lender; // The address of the lender. address internal _pendingBorrower; // The address of the pendingBorrower, the only address that can accept the borrower role. address internal _pendingLender; // The address of the pendingLender, the only address that can accept the lender role. // Assets address internal _collateralAsset; // The address of the asset used as collateral. address internal _fundsAsset; // The address of the asset used as funds. // Loan Term Parameters uint256 internal _gracePeriod; // The number of seconds a payment can be late. uint256 internal _paymentInterval; // The number of seconds between payments. // Rates uint256 internal _interestRate; // The annualized interest rate of the loan. uint256 internal _closingRate; // The fee rate (applied to principal) to close the loan. uint256 internal _lateFeeRate; // The fee rate for late payments. uint256 internal _lateInterestPremium; // The amount to increase the interest rate by for late payments. // Requested Amounts uint256 internal _collateralRequired; // The collateral the borrower is expected to put up to draw down all _principalRequested. uint256 internal _principalRequested; // The funds the borrowers wants to borrow. uint256 internal _endingPrincipal; // The principal to remain at end of loan. // State uint256 internal _drawableFunds; // The amount of funds that can be drawn down. uint256 internal __deprecated_claimableFunds; // Deprecated storage slot for `claimableFunds`. uint256 internal _collateral; // The amount of collateral, in collateral asset, that is currently posted. uint256 internal _nextPaymentDueDate; // The timestamp of due date of next payment. uint256 internal _paymentsRemaining; // The number of payments remaining. uint256 internal _principal; // The amount of principal yet to be paid down. // Refinance bytes32 internal _refinanceCommitment; // Keccak-256 hash of the parameters of proposed terms of a refinance: `refinancer_`, `deadline_`, and `calls_`. uint256 internal _refinanceInterest; // Amount of accrued interest between the last payment on a loan and the time the refinance takes effect. // Establishment fees uint256 internal __deprecated_delegateFee; // Deprecated storage slot for `delegateFee`. uint256 internal __deprecated_treasuryFee; // Deprecated storage slot for `treasuryFee`. // Pool V2 dependencies address internal _feeManager; // Address responsible for calculating and handling fees // Triggered defaults uint256 internal _originalNextPaymentDueDate; // Stores the original `nextPaymentDueDate` in order to allow triggered defaults to be reverted. }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.7; import { IMapleProxied } from "../../modules/maple-proxy-factory/contracts/interfaces/IMapleProxied.sol"; import { IMapleLoanEvents } from "./IMapleLoanEvents.sol"; /// @title MapleLoan implements a primitive loan with additional functionality, and is intended to be proxied. interface IMapleLoan is IMapleProxied, IMapleLoanEvents { /******************************************************************************************************************************/ /*** State Variables ***/ /******************************************************************************************************************************/ /** * @dev The borrower of the loan, responsible for repayments. */ function borrower() external view returns (address borrower_); /** * @dev The fee rate (applied to principal) to close the loan. * This value should be configured so that it is less expensive to close a loan with more than one payment remaining, but * more expensive to close it if on the last payment. */ function closingRate() external view returns (uint256 closingRate_); /** * @dev The amount of collateral posted against outstanding (drawn down) principal. */ function collateral() external view returns (uint256 collateral_); /** * @dev The address of the asset deposited by the borrower as collateral, if needed. */ function collateralAsset() external view returns (address collateralAsset_); /** * @dev The amount of collateral required if all of the principal required is drawn down. */ function collateralRequired() external view returns (uint256 collateralRequired_); /** * @dev The amount of funds that have yet to be drawn down by the borrower. */ function drawableFunds() external view returns (uint256 drawableFunds_); /** * @dev The portion of principal to not be paid down as part of payment installments, which would need to be paid back upon final payment. * If endingPrincipal = principal, loan is interest-only. */ function endingPrincipal() external view returns (uint256 endingPrincipal_); /** * @dev The address of the contract that handles payments of fees on behalf of the loan. */ function feeManager() external view returns (address feeManager_); /** * @dev The asset deposited by the lender to fund the loan. */ function fundsAsset() external view returns (address fundsAsset_); /** * @dev The Maple globals address */ function globals() external view returns (address globals_); /** * @dev The address of the Maple Governor. */ function governor() external view returns (address governor_); /** * @dev The amount of time the borrower has, after a payment is due, to make a payment before being in default. */ function gracePeriod() external view returns (uint256 gracePeriod_); /** * @dev The annualized interest rate (APR), in units of 1e18, (i.e. 1% is 0.01e18). */ function interestRate() external view returns (uint256 interestRate_); /** * @dev The rate charged at late payments. */ function lateFeeRate() external view returns (uint256 lateFeeRate_); /** * @dev The premium over the regular interest rate applied when paying late. */ function lateInterestPremium() external view returns (uint256 lateInterestPremium_); /** * @dev The lender of the Loan. */ function lender() external view returns (address lender_); /** * @dev The timestamp due date of the next payment. */ function nextPaymentDueDate() external view returns (uint256 nextPaymentDueDate_); /** * @dev The saved original payment due date from a loan impairment. */ function originalNextPaymentDueDate() external view returns (uint256 originalNextPaymentDueDate_); /** * @dev The specified time between loan payments. */ function paymentInterval() external view returns (uint256 paymentInterval_); /** * @dev The number of payment installments remaining for the loan. */ function paymentsRemaining() external view returns (uint256 paymentsRemaining_); /** * @dev The address of the pending borrower. */ function pendingBorrower() external view returns (address pendingBorrower_); /** * @dev The address of the pending lender. */ function pendingLender() external view returns (address pendingLender_); /** * @dev The amount of principal owed (initially, the requested amount), which needs to be paid back. */ function principal() external view returns (uint256 principal_); /** * @dev The initial principal amount requested by the borrower. */ function principalRequested() external view returns (uint256 principalRequested_); /** * @dev The hash of the proposed refinance agreement. */ function refinanceCommitment() external view returns (bytes32 refinanceCommitment_); /** * @dev Amount of unpaid interest that has accrued before a refinance was accepted. */ function refinanceInterest() external view returns (uint256 refinanceInterest_); /******************************************************************************************************************************/ /*** State Changing Functions ***/ /******************************************************************************************************************************/ /** * @dev Accept the borrower role, must be called by pendingBorrower. */ function acceptBorrower() external; /** * @dev Accept the lender role, must be called by pendingLender. */ function acceptLender() external; /** * @dev Accept the proposed terms ans trigger refinance execution * @param refinancer_ The address of the refinancer contract. * @param deadline_ The deadline for accepting the new terms. * @param calls_ The encoded arguments to be passed to refinancer. * @return refinanceCommitment_ The hash of the accepted refinance agreement. */ function acceptNewTerms(address refinancer_, uint256 deadline_, bytes[] calldata calls_) external returns (bytes32 refinanceCommitment_); /** * @dev Repay all principal and interest and close a loan. * FUNDS SHOULD NOT BE TRANSFERRED TO THIS CONTRACT NON-ATOMICALLY. IF THEY ARE, THE BALANCE MAY BE STOLEN USING `skim`. * @param amount_ An amount to pull from the caller, if any. * @return principal_ The portion of the amount paying back principal. * @return interest_ The portion of the amount paying interest. * @return fees_ The portion of the amount paying service fees. */ function closeLoan(uint256 amount_) external returns (uint256 principal_, uint256 interest_, uint256 fees_); /** * @dev Draw down funds from the loan. * @param amount_ The amount to draw down. * @param destination_ The address to send the funds. * @return collateralPosted_ The amount of additional collateral posted, if any. */ function drawdownFunds(uint256 amount_, address destination_) external returns (uint256 collateralPosted_); /** * @dev Lend funds to the loan/borrower. * @param lender_ The address to be registered as the lender. * @return fundsLent_ The amount funded. */ function fundLoan(address lender_) external returns (uint256 fundsLent_); /** * @dev Make a payment to the loan. * FUNDS SHOULD NOT BE TRANSFERRED TO THIS CONTRACT NON-ATOMICALLY. IF THEY ARE, THE BALANCE MAY BE STOLEN USING `skim`. * @param amount_ An amount to pull from the caller, if any. * @return principal_ The portion of the amount paying back principal. * @return interest_ The portion of the amount paying interest fees. * @return fees_ The portion of the amount paying service fees. */ function makePayment(uint256 amount_) external returns (uint256 principal_, uint256 interest_, uint256 fees_); /** * @dev Post collateral to the loan. * FUNDS SHOULD NOT BE TRANSFERRED TO THIS CONTRACT NON-ATOMICALLY. IF THEY ARE, THE BALANCE MAY BE STOLEN USING `skim`. * @param amount_ An amount to pull from the caller, if any. * @return collateralPosted_ The amount posted. */ function postCollateral(uint256 amount_) external returns (uint256 collateralPosted_); /** * @dev Propose new terms for refinance. * @param refinancer_ The address of the refinancer contract. * @param deadline_ The deadline for accepting the new terms. * @param calls_ The encoded arguments to be passed to refinancer. * @return refinanceCommitment_ The hash of the proposed refinance agreement. */ function proposeNewTerms(address refinancer_, uint256 deadline_, bytes[] calldata calls_) external returns (bytes32 refinanceCommitment_); /** * @dev Nullify the current proposed terms. * @param refinancer_ The address of the refinancer contract. * @param deadline_ The deadline for accepting the new terms. * @param calls_ The encoded arguments to be passed to refinancer. * @return refinanceCommitment_ The hash of the rejected refinance agreement. */ function rejectNewTerms(address refinancer_, uint256 deadline_, bytes[] calldata calls_) external returns (bytes32 refinanceCommitment_); /** * @dev Remove collateral from the loan (opposite of posting collateral). * @param amount_ The amount removed. * @param destination_ The destination to send the removed collateral. */ function removeCollateral(uint256 amount_, address destination_) external; /** * @dev Remove the loan impairment by restoring the original payment due date. */ function removeLoanImpairment() external; /** * @dev Return funds to the loan (opposite of drawing down). * FUNDS SHOULD NOT BE TRANSFERRED TO THIS CONTRACT NON-ATOMICALLY. IF THEY ARE, THE BALANCE MAY BE STOLEN USING `skim`. * @param amount_ An amount to pull from the caller, if any. * @return fundsReturned_ The amount returned. */ function returnFunds(uint256 amount_) external returns (uint256 fundsReturned_); /** * @dev Repossess collateral, and any funds, for a loan in default. * @param destination_ The address where the collateral and funds asset is to be sent, if any. * @return collateralRepossessed_ The amount of collateral asset repossessed. * @return fundsRepossessed_ The amount of funds asset repossessed. */ function repossess(address destination_) external returns (uint256 collateralRepossessed_, uint256 fundsRepossessed_); /** * @dev Set the pendingBorrower to a new account. * @param pendingBorrower_ The address of the new pendingBorrower. */ function setPendingBorrower(address pendingBorrower_) external; /** * @dev Set the pendingLender to a new account. * @param pendingLender_ The address of the new pendingLender. */ function setPendingLender(address pendingLender_) external; /** * @dev Remove all token that is not accounted for by the loan (i.e. not `collateral` or `drawableFunds`). * @param token_ The address of the token contract. * @param destination_ The recipient of the token. * @return skimmed_ The amount of token removed from the loan. */ function skim(address token_, address destination_) external returns (uint256 skimmed_); /** * @dev Fast forward the next payment due date to the current time. * This enables the pool delegate to force a payment (or default). */ function impairLoan() external; /******************************************************************************************************************************/ /*** View Functions ***/ /******************************************************************************************************************************/ /** * @dev Returns the excess collateral that can be removed. * @return excessCollateral_ The excess collateral that can be removed, if any. */ function excessCollateral() external view returns (uint256 excessCollateral_); /** * @dev Get the additional collateral to be posted to drawdown some amount. * @param drawdown_ The amount desired to be drawn down. * @return additionalCollateral_ The additional collateral that must be posted, if any. */ function getAdditionalCollateralRequiredFor(uint256 drawdown_) external view returns (uint256 additionalCollateral_); /** * @dev Get the breakdown of the total payment needed to satisfy an early repayment to close the loan. * @return principal_ The portion of the total amount that will go towards principal. * @return interest_ The portion of the total amount that will go towards interest fees. * @return fees_ The portion of the total amount that will go towards fees. */ function getClosingPaymentBreakdown() external view returns (uint256 principal_, uint256 interest_, uint256 fees_); /** * @dev Get the breakdown of the total payment needed to satisfy the next payment installment. * @return principal_ The portion of the total amount that will go towards principal. * @return interest_ The portion of the total amount that will go towards interest fees. * @return fees_ The portion of the total amount that will go towards paying administrative fees. */ function getNextPaymentBreakdown() external view returns (uint256 principal_, uint256 interest_, uint256 fees_); /** * @dev Get the detailed breakdown of the total payment needed to satisfy the next payment installment. * @return principal_ The portion of the total amount that will go towards principal. * @return interest_ The portion of the total amount that will go towards interest fees. * [0] Interest from the payment interval. * [1] Late interest. * [2] Refinance interest. * @return fees_ The portion of the total amount that will go towards paying administrative fees. * [0] Delegate fees. * [1] Platform fees. */ function getNextPaymentDetailedBreakdown() external view returns (uint256 principal_, uint256[3] memory interest_, uint256[2] memory fees_); /** * @dev Get the extra interest that will be charged according to loan terms before refinance, based on a given timestamp. * @param timestamp_ The timestamp when the new terms will be accepted. * @return proRataInterest_ The interest portion to be added in the next payment. */ function getRefinanceInterest(uint256 timestamp_) external view returns (uint256 proRataInterest_); /** * @dev Get the amount on an asset that in not accounted for by the accounting variables (and thus can be skimmed). * @param asset_ The address of a asset contract. * @return unaccountedAmount_ The amount that is not accounted for. */ function getUnaccountedAmount(address asset_) external view returns (uint256 unaccountedAmount_); /** * @dev Return if the loan has been impaired. * @return isImpaired_ Is the loan impaired or not. */ function isImpaired() external view returns (bool isImpaired_); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.7; /// @title IMapleLoanEvents defines the events for a MapleLoan. interface IMapleLoanEvents { /** * @dev Borrower was accepted, and set to a new account. * @param borrower_ The address of the new borrower. */ event BorrowerAccepted(address indexed borrower_); /** * @dev Collateral was posted. * @param amount_ The amount of collateral posted. */ event CollateralPosted(uint256 amount_); /** * @dev Collateral was removed. * @param amount_ The amount of collateral removed. * @param destination_ The recipient of the collateral removed. */ event CollateralRemoved(uint256 amount_, address indexed destination_); /** * @dev The loan was funded. * @param lender_ The address of the lender. * @param amount_ The amount funded. * @param nextPaymentDueDate_ The due date of the next payment. */ event Funded(address indexed lender_, uint256 amount_, uint256 nextPaymentDueDate_); /** * @dev Funds were claimed. * @param amount_ The amount of funds claimed. * @param destination_ The recipient of the funds claimed. */ event FundsClaimed(uint256 amount_, address indexed destination_); /** * @dev Funds were drawn. * @param amount_ The amount of funds drawn. * @param destination_ The recipient of the funds drawn down. */ event FundsDrawnDown(uint256 amount_, address indexed destination_); /** * @dev Funds were returned. * @param amount_ The amount of funds returned. */ event FundsReturned(uint256 amount_); /** * @dev Loan was initialized. * @param borrower_ The address of the borrower. * @param feeManager_ The address of the entity responsible for calculating fees * @param assets_ Array of asset addresses. * [0]: collateralAsset, * [1]: fundsAsset. * @param termDetails_ Array of loan parameters: * [0]: gracePeriod, * [1]: paymentInterval, * [2]: payments, * @param amounts_ Requested amounts: * [0]: collateralRequired, * [1]: principalRequested, * [2]: endingPrincipal. * @param rates_ Fee parameters: * [0]: interestRate, * [1]: closingFeeRate, * [2]: lateFeeRate, * [3]: lateInterestPremium * @param fees_ Array of fees: * [0]: delegateOriginationFee, * [1]: delegateServiceFee */ event Initialized( address indexed borrower_, address indexed feeManager_, address[2] assets_, uint256[3] termDetails_, uint256[3] amounts_, uint256[4] rates_, uint256[2] fees_ ); /** * @dev Lender was accepted, and set to a new account. * @param lender_ The address of the new lender. */ event LenderAccepted(address indexed lender_); /** * @dev The next payment due date was fast forwarded to the current time, activating the grace period. * This is emitted when the pool delegate wants to force a payment (or default). * @param nextPaymentDueDate_ The new next payment due date. */ event LoanImpaired(uint256 nextPaymentDueDate_); /** * @dev Loan was repaid early and closed. * @param principalPaid_ The portion of the total amount that went towards principal. * @param interestPaid_ The portion of the total amount that went towards interest. * @param feesPaid_ The portion of the total amount that went towards fees. */ event LoanClosed(uint256 principalPaid_, uint256 interestPaid_, uint256 feesPaid_); /** * @dev The terms of the refinance proposal were accepted. * @param refinanceCommitment_ The hash of the refinancer, deadline, and calls proposed. * @param refinancer_ The address that will execute the refinance. * @param deadline_ The deadline for accepting the new terms. * @param calls_ The individual calls for the refinancer contract. */ event NewTermsAccepted(bytes32 refinanceCommitment_, address refinancer_, uint256 deadline_, bytes[] calls_); /** * @dev A refinance was proposed. * @param refinanceCommitment_ The hash of the refinancer, deadline, and calls proposed. * @param refinancer_ The address that will execute the refinance. * @param deadline_ The deadline for accepting the new terms. * @param calls_ The individual calls for the refinancer contract. */ event NewTermsProposed(bytes32 refinanceCommitment_, address refinancer_, uint256 deadline_, bytes[] calls_); /** * @dev The terms of the refinance proposal were rejected. * @param refinanceCommitment_ The hash of the refinancer, deadline, and calls proposed. * @param refinancer_ The address that will execute the refinance. * @param deadline_ The deadline for accepting the new terms. * @param calls_ The individual calls for the refinancer contract. */ event NewTermsRejected(bytes32 refinanceCommitment_, address refinancer_, uint256 deadline_, bytes[] calls_); /** * @dev The next payment due date was restored to it's original value, reverting the action of loan impairment. * @param nextPaymentDueDate_ The new next payment due date. */ event NextPaymentDueDateRestored(uint256 nextPaymentDueDate_); /** * @dev Payments were made. * @param principalPaid_ The portion of the total amount that went towards principal. * @param interestPaid_ The portion of the total amount that went towards interest. * @param fees_ The portion of the total amount that went towards fees. */ event PaymentMade(uint256 principalPaid_, uint256 interestPaid_, uint256 fees_); /** * @dev Pending borrower was set. * @param pendingBorrower_ Address that can accept the borrower role. */ event PendingBorrowerSet(address pendingBorrower_); /** * @dev Pending lender was set. * @param pendingLender_ Address that can accept the lender role. */ event PendingLenderSet(address pendingLender_); /** * @dev The loan was in default and funds and collateral was repossessed by the lender. * @param collateralRepossessed_ The amount of collateral asset repossessed. * @param fundsRepossessed_ The amount of funds asset repossessed. * @param destination_ The recipient of the collateral and funds, if any. */ event Repossessed(uint256 collateralRepossessed_, uint256 fundsRepossessed_, address indexed destination_); /** * @dev Some token (neither fundsAsset nor collateralAsset) was removed from the loan. * @param token_ The address of the token contract. * @param amount_ The amount of token remove from the loan. * @param destination_ The recipient of the token. */ event Skimmed(address indexed token_, uint256 amount_, address indexed destination_); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.7; interface IMapleLoanFeeManager { /******************************************************************************************************************************/ /*** Events ***/ /******************************************************************************************************************************/ /** * @dev New fee terms have been set. * @param loan_ The address of the loan contract. * @param delegateOriginationFee_ The new value for delegate origination fee. * @param delegateServiceFee_ The new value for delegate service fee. */ event FeeTermsUpdated(address loan_, uint256 delegateOriginationFee_, uint256 delegateServiceFee_); /** * @dev A fee payment was made. * @param loan_ The address of the loan contract. * @param delegateOriginationFee_ The amount of delegate origination fee paid. * @param platformOriginationFee_ The amount of platform origination fee paid. */ event OriginationFeesPaid(address loan_, uint256 delegateOriginationFee_, uint256 platformOriginationFee_); /** * @dev New fee terms have been set. * @param loan_ The address of the loan contract. * @param platformServiceFee_ The new value for the platform service fee. */ event PlatformServiceFeeUpdated(address loan_, uint256 platformServiceFee_); /** * @dev New fee terms have been set. * @param loan_ The address of the loan contract. * @param partialPlatformServiceFee_ The value for the platform service fee. * @param partialDelegateServiceFee_ The value for the delegate service fee. */ event PartialRefinanceServiceFeesUpdated(address loan_, uint256 partialPlatformServiceFee_, uint256 partialDelegateServiceFee_); /** * @dev A fee payment was made. * @param loan_ The address of the loan contract. * @param delegateServiceFee_ The amount of delegate service fee paid. * @param partialRefinanceDelegateServiceFee_ The amount of partial delegate service fee from refinance paid. * @param platformServiceFee_ The amount of platform service fee paid. * @param partialRefinancePlatformServiceFee_ The amount of partial platform service fee from refinance paid. */ event ServiceFeesPaid(address loan_, uint256 delegateServiceFee_, uint256 partialRefinanceDelegateServiceFee_, uint256 platformServiceFee_, uint256 partialRefinancePlatformServiceFee_); /******************************************************************************************************************************/ /*** Payment Functions ***/ /******************************************************************************************************************************/ /** * @dev Called during `makePayment`, performs fee payments to the pool delegate and treasury. * @param asset_ The address asset in which fees were paid. * @param numberOfPayments_ The number of payments for which service fees will be paid. */ function payServiceFees(address asset_, uint256 numberOfPayments_) external returns (uint256 feePaid_); /** * @dev Called during `fundLoan`, performs fee payments to poolDelegate and treasury. * @param asset_ The address asset in which fees were paid. * @param principalRequested_ The total amount of principal requested, which will be used to calculate fees. * @return feePaid_ The total amount of fees paid. */ function payOriginationFees(address asset_, uint256 principalRequested_) external returns (uint256 feePaid_); /******************************************************************************************************************************/ /*** Fee Update Functions ***/ /******************************************************************************************************************************/ /** * @dev Called during loan creation or refinance, sets the fee terms. * @param delegateOriginationFee_ The amount of delegate origination fee to be paid. * @param delegateServiceFee_ The amount of delegate service fee to be paid. */ function updateDelegateFeeTerms(uint256 delegateOriginationFee_, uint256 delegateServiceFee_) external; /** * @dev Called during loan refinance to save the partial service fees accrued. * @param principalRequested_ The amount of principal pre-refinance requested. * @param timeSinceLastDueDate_ The amount of time since last payment due date. */ function updateRefinanceServiceFees(uint256 principalRequested_, uint256 timeSinceLastDueDate_) external; /** * @dev Function called by loans to update the saved platform service fee rate. */ function updatePlatformServiceFee(uint256 principalRequested_, uint256 paymentInterval_) external; /******************************************************************************************************************************/ /*** View Functions ***/ /******************************************************************************************************************************/ /** * @dev Gets the delegate origination fee for the given loan. * @param loan_ The address of the loan contract. * @return delegateOriginationFee_ The amount of origination to be paid to delegate. */ function delegateOriginationFee(address loan_) external view returns (uint256 delegateOriginationFee_); /** * @dev Gets the delegate service fee rate for the given loan. * @param loan_ The address of the loan contract. * @return delegateServiceFee_ The amount of delegate service fee to be paid. */ function delegateServiceFee(address loan_) external view returns (uint256 delegateServiceFee_); /** * @dev Gets the delegate service fee rate for the given loan. * @param loan_ The address of the loan contract. * @return delegateRefinanceServiceFee_ The amount of delegate service fee to be paid. */ function delegateRefinanceServiceFee(address loan_) external view returns (uint256 delegateRefinanceServiceFee_); /** * @dev Gets the delegate service fee for the given loan. * @param loan_ The address of the loan contract. * @param interval_ The time, in seconds, to get the proportional fee for * @return delegateServiceFee_ The amount of delegate service fee to be paid. */ function getDelegateServiceFeesForPeriod(address loan_, uint256 interval_) external view returns (uint256 delegateServiceFee_); /** * @dev Gets the sum of all origination fees for the given loan. * @param loan_ The address of the loan contract. * @param principalRequested_ The amount of principal requested in the loan. * @return originationFees_ The amount of origination fees to be paid. */ function getOriginationFees(address loan_, uint256 principalRequested_) external view returns (uint256 originationFees_); /** * @dev Gets the platform origination fee value for the given loan. * @param loan_ The address of the loan contract. * @param principalRequested_ The amount of principal requested in the loan. * @return platformOriginationFee_ The amount of platform origination fee to be paid. */ function getPlatformOriginationFee(address loan_, uint256 principalRequested_) external view returns (uint256 platformOriginationFee_); /** * @dev Gets the delegate service fee for the given loan. * @param loan_ The address of the loan contract. * @param principalRequested_ The amount of principal requested in the loan. * @param interval_ The time, in seconds, to get the proportional fee for * @return platformServiceFee_ The amount of platform service fee to be paid. */ function getPlatformServiceFeeForPeriod(address loan_, uint256 principalRequested_, uint256 interval_) external view returns (uint256 platformServiceFee_); /** * @dev Gets the service fees for the given interval. * @param loan_ The address of the loan contract. * @param numberOfPayments_ The number of payments being paid. * @return delegateServiceFee_ The amount of delegate service fee to be paid. * @return delegateRefinanceFee_ The amount of delegate refinance fee to be paid. * @return platformServiceFee_ The amount of platform service fee to be paid. * @return platformRefinanceFee_ The amount of platform refinance fee to be paid. */ function getServiceFeeBreakdown(address loan_, uint256 numberOfPayments_) external view returns ( uint256 delegateServiceFee_, uint256 delegateRefinanceFee_, uint256 platformServiceFee_, uint256 platformRefinanceFee_ ); /** * @dev Gets the service fees for the given interval. * @param loan_ The address of the loan contract. * @param numberOfPayments_ The number of payments being paid. * @return serviceFees_ The amount of platform service fee to be paid. */ function getServiceFees(address loan_, uint256 numberOfPayments_) external view returns (uint256 serviceFees_); /** * @dev Gets the service fees for the given interval. * @param loan_ The address of the loan contract. * @param interval_ The time, in seconds, to get the proportional fee for * @return serviceFees_ The amount of platform service fee to be paid. */ function getServiceFeesForPeriod(address loan_, uint256 interval_) external view returns (uint256 serviceFees_); /** * @dev Gets the global contract address. * @return globals_ The address of the global contract. */ function globals() external view returns (address globals_); /** * @dev Gets the platform fee rate for the given loan. * @param loan_ The address of the loan contract. * @return platformRefinanceServiceFee_ The amount of platform service fee to be paid. */ function platformRefinanceServiceFee(address loan_) external view returns (uint256 platformRefinanceServiceFee_); /** * @dev Gets the platform fee rate for the given loan. * @param loan_ The address of the loan contract. * @return platformServiceFee The amount of platform service fee to be paid. */ function platformServiceFee(address loan_) external view returns (uint256 platformServiceFee); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.7; interface IMapleGlobalsLike { function governor() external view returns (address governor_); function isBorrower(address account_) external view returns (bool isBorrower_); function isCollateralAsset(address collateralAsset_) external view returns (bool isCollateralAsset_); function isFactory(bytes32 factoryId_, address factory_) external view returns (bool isValid_); function isPoolAsset(address poolAsset_) external view returns (bool isValid_); function mapleTreasury() external view returns (address governor_); function platformOriginationFeeRate(address pool_) external view returns (uint256 platformOriginationFeeRate_); function platformServiceFeeRate(address pool_) external view returns (uint256 platformFee_); function protocolPaused() external view returns (bool protocolPaused_); function securityAdmin() external view returns (address securityAdmin_); } interface ILenderLike { function claim(uint256 principal_, uint256 interest_, uint256 previousPaymentDueDate_, uint256 nextPaymentDueDate_) external; function factory() external view returns (address factory_); } interface ILoanLike { function factory() external view returns (address factory_); function fundsAsset() external view returns (address asset_); function lender() external view returns (address lender_); function paymentInterval() external view returns (uint256 paymentInterval_); function paymentsRemaining() external view returns (uint256 paymentsRemaining_); function principal() external view returns (uint256 principal_); function principalRequested() external view returns (uint256 principalRequested_); } interface ILoanManagerLike { function owner() external view returns (address owner_); function poolManager() external view returns (address poolManager_); } interface IMapleFeeManagerLike { function updateDelegateFeeTerms(uint256 delegateOriginationFee_, uint256 delegateServiceFee_) external; function updatePlatformServiceFee(uint256 principalRequested_, uint256 paymentInterval_) external; } interface IMapleProxyFactoryLike { function isInstance(address instance_) external view returns (bool isInstance_); function mapleGlobals() external view returns (address mapleGlobals_); } interface IPoolManagerLike { function poolDelegate() external view returns (address poolDelegate_); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.7; /// @title Interface of the ERC20 standard as defined in the EIP, including EIP-2612 permit functionality. interface IERC20 { /**************/ /*** Events ***/ /**************/ /** * @dev Emitted when one account has set the allowance of another account over their tokens. * @param owner_ Account that tokens are approved from. * @param spender_ Account that tokens are approved for. * @param amount_ Amount of tokens that have been approved. */ event Approval(address indexed owner_, address indexed spender_, uint256 amount_); /** * @dev Emitted when tokens have moved from one account to another. * @param owner_ Account that tokens have moved from. * @param recipient_ Account that tokens have moved to. * @param amount_ Amount of tokens that have been transferred. */ event Transfer(address indexed owner_, address indexed recipient_, uint256 amount_); /**************************/ /*** External Functions ***/ /**************************/ /** * @dev Function that allows one account to set the allowance of another account over their tokens. * Emits an {Approval} event. * @param spender_ Account that tokens are approved for. * @param amount_ Amount of tokens that have been approved. * @return success_ Boolean indicating whether the operation succeeded. */ function approve(address spender_, uint256 amount_) external returns (bool success_); /** * @dev Function that allows one account to decrease the allowance of another account over their tokens. * Emits an {Approval} event. * @param spender_ Account that tokens are approved for. * @param subtractedAmount_ Amount to decrease approval by. * @return success_ Boolean indicating whether the operation succeeded. */ function decreaseAllowance(address spender_, uint256 subtractedAmount_) external returns (bool success_); /** * @dev Function that allows one account to increase the allowance of another account over their tokens. * Emits an {Approval} event. * @param spender_ Account that tokens are approved for. * @param addedAmount_ Amount to increase approval by. * @return success_ Boolean indicating whether the operation succeeded. */ function increaseAllowance(address spender_, uint256 addedAmount_) external returns (bool success_); /** * @dev Approve by signature. * @param owner_ Owner address that signed the permit. * @param spender_ Spender of the permit. * @param amount_ Permit approval spend limit. * @param deadline_ Deadline after which the permit is invalid. * @param v_ ECDSA signature v component. * @param r_ ECDSA signature r component. * @param s_ ECDSA signature s component. */ function permit(address owner_, address spender_, uint amount_, uint deadline_, uint8 v_, bytes32 r_, bytes32 s_) external; /** * @dev Moves an amount of tokens from `msg.sender` to a specified account. * Emits a {Transfer} event. * @param recipient_ Account that receives tokens. * @param amount_ Amount of tokens that are transferred. * @return success_ Boolean indicating whether the operation succeeded. */ function transfer(address recipient_, uint256 amount_) external returns (bool success_); /** * @dev Moves a pre-approved amount of tokens from a sender to a specified account. * Emits a {Transfer} event. * Emits an {Approval} event. * @param owner_ Account that tokens are moving from. * @param recipient_ Account that receives tokens. * @param amount_ Amount of tokens that are transferred. * @return success_ Boolean indicating whether the operation succeeded. */ function transferFrom(address owner_, address recipient_, uint256 amount_) external returns (bool success_); /**********************/ /*** View Functions ***/ /**********************/ /** * @dev Returns the allowance that one account has given another over their tokens. * @param owner_ Account that tokens are approved from. * @param spender_ Account that tokens are approved for. * @return allowance_ Allowance that one account has given another over their tokens. */ function allowance(address owner_, address spender_) external view returns (uint256 allowance_); /** * @dev Returns the amount of tokens owned by a given account. * @param account_ Account that owns the tokens. * @return balance_ Amount of tokens owned by a given account. */ function balanceOf(address account_) external view returns (uint256 balance_); /** * @dev Returns the decimal precision used by the token. * @return decimals_ The decimal precision used by the token. */ function decimals() external view returns (uint8 decimals_); /** * @dev Returns the signature domain separator. * @return domainSeparator_ The signature domain separator. */ function DOMAIN_SEPARATOR() external view returns (bytes32 domainSeparator_); /** * @dev Returns the name of the token. * @return name_ The name of the token. */ function name() external view returns (string memory name_); /** * @dev Returns the nonce for the given owner. * @param owner_ The address of the owner account. * @return nonce_ The nonce for the given owner. */ function nonces(address owner_) external view returns (uint256 nonce_); /** * @dev Returns the permit type hash. * @return permitTypehash_ The permit type hash. */ function PERMIT_TYPEHASH() external view returns (bytes32 permitTypehash_); /** * @dev Returns the symbol of the token. * @return symbol_ The symbol of the token. */ function symbol() external view returns (string memory symbol_); /** * @dev Returns the total amount of tokens in existence. * @return totalSupply_ The total amount of tokens in existence. */ function totalSupply() external view returns (uint256 totalSupply_); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.7; import { IERC20Like } from "./interfaces/IERC20Like.sol"; /** * @title Small Library to standardize erc20 token interactions. */ library ERC20Helper { /**************************/ /*** Internal Functions ***/ /**************************/ function transfer(address token_, address to_, uint256 amount_) internal returns (bool success_) { return _call(token_, abi.encodeWithSelector(IERC20Like.transfer.selector, to_, amount_)); } function transferFrom(address token_, address from_, address to_, uint256 amount_) internal returns (bool success_) { return _call(token_, abi.encodeWithSelector(IERC20Like.transferFrom.selector, from_, to_, amount_)); } function approve(address token_, address spender_, uint256 amount_) internal returns (bool success_) { // If setting approval to zero fails, return false. if (!_call(token_, abi.encodeWithSelector(IERC20Like.approve.selector, spender_, uint256(0)))) return false; // If `amount_` is zero, return true as the previous step already did this. if (amount_ == uint256(0)) return true; // Return the result of setting the approval to `amount_`. return _call(token_, abi.encodeWithSelector(IERC20Like.approve.selector, spender_, amount_)); } function _call(address token_, bytes memory data_) private returns (bool success_) { if (token_.code.length == uint256(0)) return false; bytes memory returnData; ( success_, returnData ) = token_.call(data_); return success_ && (returnData.length == uint256(0) || abi.decode(returnData, (bool))); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.7; /// @title Interface of the ERC20 standard as needed by ERC20Helper. interface IERC20Like { function approve(address spender_, uint256 amount_) external returns (bool success_); function transfer(address recipient_, uint256 amount_) external returns (bool success_); function transferFrom(address owner_, address recipient_, uint256 amount_) external returns (bool success_); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity 0.8.7; import { ProxiedInternals } from "../modules/proxy-factory/contracts/ProxiedInternals.sol"; /// @title A Maple implementation that is to be proxied, will need MapleProxiedInternals. abstract contract MapleProxiedInternals is ProxiedInternals {}
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity 0.8.7; import { IProxied } from "../../modules/proxy-factory/contracts/interfaces/IProxied.sol"; /// @title A Maple implementation that is to be proxied, must implement IMapleProxied. interface IMapleProxied is IProxied { /** * @dev The instance was upgraded. * @param toVersion_ The new version of the loan. * @param arguments_ The upgrade arguments, if any. */ event Upgraded(uint256 toVersion_, bytes arguments_); /** * @dev Upgrades a contract implementation to a specific version. * Access control logic critical since caller can force a selfdestruct via a malicious `migrator_` which is delegatecalled. * @param toVersion_ The version to upgrade to. * @param arguments_ Some encoded arguments to use for the upgrade. */ function upgrade(uint256 toVersion_, bytes calldata arguments_) external; }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity 0.8.7; import { IDefaultImplementationBeacon } from "../../modules/proxy-factory/contracts/interfaces/IDefaultImplementationBeacon.sol"; /// @title A Maple factory for Proxy contracts that proxy MapleProxied implementations. interface IMapleProxyFactory is IDefaultImplementationBeacon { /**************/ /*** Events ***/ /**************/ /** * @dev A default version was set. * @param version_ The default version. */ event DefaultVersionSet(uint256 indexed version_); /** * @dev A version of an implementation, at some address, was registered, with an optional initializer. * @param version_ The version registered. * @param implementationAddress_ The address of the implementation. * @param initializer_ The address of the initializer, if any. */ event ImplementationRegistered(uint256 indexed version_, address indexed implementationAddress_, address indexed initializer_); /** * @dev A proxy contract was deployed with some initialization arguments. * @param version_ The version of the implementation being proxied by the deployed proxy contract. * @param instance_ The address of the proxy contract deployed. * @param initializationArguments_ The arguments used to initialize the proxy contract, if any. */ event InstanceDeployed(uint256 indexed version_, address indexed instance_, bytes initializationArguments_); /** * @dev A instance has upgraded by proxying to a new implementation, with some migration arguments. * @param instance_ The address of the proxy contract. * @param fromVersion_ The initial implementation version being proxied. * @param toVersion_ The new implementation version being proxied. * @param migrationArguments_ The arguments used to migrate, if any. */ event InstanceUpgraded(address indexed instance_, uint256 indexed fromVersion_, uint256 indexed toVersion_, bytes migrationArguments_); /** * @dev The MapleGlobals was set. * @param mapleGlobals_ The address of a Maple Globals contract. */ event MapleGlobalsSet(address indexed mapleGlobals_); /** * @dev An upgrade path was disabled, with an optional migrator contract. * @param fromVersion_ The starting version of the upgrade path. * @param toVersion_ The destination version of the upgrade path. */ event UpgradePathDisabled(uint256 indexed fromVersion_, uint256 indexed toVersion_); /** * @dev An upgrade path was enabled, with an optional migrator contract. * @param fromVersion_ The starting version of the upgrade path. * @param toVersion_ The destination version of the upgrade path. * @param migrator_ The address of the migrator, if any. */ event UpgradePathEnabled(uint256 indexed fromVersion_, uint256 indexed toVersion_, address indexed migrator_); /***********************/ /*** State Variables ***/ /***********************/ /** * @dev The default version. */ function defaultVersion() external view returns (uint256 defaultVersion_); /** * @dev The address of the MapleGlobals contract. */ function mapleGlobals() external view returns (address mapleGlobals_); /** * @dev Whether the upgrade is enabled for a path from a version to another version. * @param toVersion_ The initial version. * @param fromVersion_ The destination version. * @return allowed_ Whether the upgrade is enabled. */ function upgradeEnabledForPath(uint256 toVersion_, uint256 fromVersion_) external view returns (bool allowed_); /********************************/ /*** State Changing Functions ***/ /********************************/ /** * @dev Deploys a new instance proxying the default implementation version, with some initialization arguments. * Uses a nonce and `msg.sender` as a salt for the CREATE2 opcode during instantiation to produce deterministic addresses. * @param arguments_ The initialization arguments to use for the instance deployment, if any. * @param salt_ The salt to use in the contract creation process. * @return instance_ The address of the deployed proxy contract. */ function createInstance(bytes calldata arguments_, bytes32 salt_) external returns (address instance_); /** * @dev Enables upgrading from a version to a version of an implementation, with an optional migrator. * Only the Governor can call this function. * @param fromVersion_ The starting version of the upgrade path. * @param toVersion_ The destination version of the upgrade path. * @param migrator_ The address of the migrator, if any. */ function enableUpgradePath(uint256 fromVersion_, uint256 toVersion_, address migrator_) external; /** * @dev Disables upgrading from a version to a version of a implementation. * Only the Governor can call this function. * @param fromVersion_ The starting version of the upgrade path. * @param toVersion_ The destination version of the upgrade path. */ function disableUpgradePath(uint256 fromVersion_, uint256 toVersion_) external; /** * @dev Registers the address of an implementation contract as a version, with an optional initializer. * Only the Governor can call this function. * @param version_ The version to register. * @param implementationAddress_ The address of the implementation. * @param initializer_ The address of the initializer, if any. */ function registerImplementation(uint256 version_, address implementationAddress_, address initializer_) external; /** * @dev Sets the default version. * Only the Governor can call this function. * @param version_ The implementation version to set as the default. */ function setDefaultVersion(uint256 version_) external; /** * @dev Sets the Maple Globals contract. * Only the Governor can call this function. * @param mapleGlobals_ The address of a Maple Globals contract. */ function setGlobals(address mapleGlobals_) external; /** * @dev Upgrades the calling proxy contract's implementation, with some migration arguments. * @param toVersion_ The implementation version to upgrade the proxy contract to. * @param arguments_ The migration arguments, if any. */ function upgradeInstance(uint256 toVersion_, bytes calldata arguments_) external; /**********************/ /*** View Functions ***/ /**********************/ /** * @dev Returns the deterministic address of a potential proxy, given some arguments and salt. * @param arguments_ The initialization arguments to be used when deploying the proxy. * @param salt_ The salt to be used when deploying the proxy. * @return instanceAddress_ The deterministic address of a potential proxy. */ function getInstanceAddress(bytes calldata arguments_, bytes32 salt_) external view returns (address instanceAddress_); /** * @dev Returns the address of an implementation version. * @param version_ The implementation version. * @return implementation_ The address of the implementation. */ function implementationOf(uint256 version_) external view returns (address implementation_); /** * @dev Returns the address of a migrator contract for a migration path (from version, to version). * If oldVersion_ == newVersion_, the migrator is an initializer. * @param oldVersion_ The old version. * @param newVersion_ The new version. * @return migrator_ The address of a migrator contract. */ function migratorForPath(uint256 oldVersion_, uint256 newVersion_) external view returns (address migrator_); /** * @dev Returns the version of an implementation contract. * @param implementation_ The address of an implementation contract. * @return version_ The version of the implementation contract. */ function versionOf(address implementation_) external view returns (uint256 version_); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.7; import { SlotManipulatable } from "./SlotManipulatable.sol"; /// @title An implementation that is to be proxied, will need ProxiedInternals. abstract contract ProxiedInternals is SlotManipulatable { /// @dev Storage slot with the address of the current factory. `keccak256('eip1967.proxy.factory') - 1`. bytes32 private constant FACTORY_SLOT = bytes32(0x7a45a402e4cb6e08ebc196f20f66d5d30e67285a2a8aa80503fa409e727a4af1); /// @dev Storage slot with the address of the current factory. `keccak256('eip1967.proxy.implementation') - 1`. bytes32 private constant IMPLEMENTATION_SLOT = bytes32(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc); /// @dev Delegatecalls to a migrator contract to manipulate storage during an initialization or migration. function _migrate(address migrator_, bytes calldata arguments_) internal virtual returns (bool success_) { uint256 size; assembly { size := extcodesize(migrator_) } if (size == uint256(0)) return false; ( success_, ) = migrator_.delegatecall(arguments_); } /// @dev Sets the factory address in storage. function _setFactory(address factory_) internal virtual returns (bool success_) { _setSlotValue(FACTORY_SLOT, bytes32(uint256(uint160(factory_)))); return true; } /// @dev Sets the implementation address in storage. function _setImplementation(address implementation_) internal virtual returns (bool success_) { _setSlotValue(IMPLEMENTATION_SLOT, bytes32(uint256(uint160(implementation_)))); return true; } /// @dev Returns the factory address. function _factory() internal view virtual returns (address factory_) { return address(uint160(uint256(_getSlotValue(FACTORY_SLOT)))); } /// @dev Returns the implementation address. function _implementation() internal view virtual returns (address implementation_) { return address(uint160(uint256(_getSlotValue(IMPLEMENTATION_SLOT)))); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.7; abstract contract SlotManipulatable { function _getReferenceTypeSlot(bytes32 slot_, bytes32 key_) internal pure returns (bytes32 value_) { return keccak256(abi.encodePacked(key_, slot_)); } function _getSlotValue(bytes32 slot_) internal view returns (bytes32 value_) { assembly { value_ := sload(slot_) } } function _setSlotValue(bytes32 slot_, bytes32 value_) internal { assembly { sstore(slot_, value_) } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.7; /// @title An beacon that provides a default implementation for proxies, must implement IDefaultImplementationBeacon. interface IDefaultImplementationBeacon { /// @dev The address of an implementation for proxies. function defaultImplementation() external view returns (address defaultImplementation_); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.7; /// @title An implementation that is to be proxied, must implement IProxied. interface IProxied { /** * @dev The address of the proxy factory. */ function factory() external view returns (address factory_); /** * @dev The address of the implementation contract being proxied. */ function implementation() external view returns (address implementation_); /** * @dev Modifies the proxy's implementation address. * @param newImplementation_ The address of an implementation contract. */ function setImplementation(address newImplementation_) external; /** * @dev Modifies the proxy's storage by delegate-calling a migrator contract with some arguments. * Access control logic critical since caller can force a selfdestruct via a malicious `migrator_` which is delegatecalled. * @param migrator_ The address of a migrator contract. * @param arguments_ Some encoded arguments to use for the migration. */ function migrate(address migrator_, bytes calldata arguments_) external; }
{ "remappings": [ "contract-test-utils/=modules/contract-test-utils/contracts/", "erc20-helper/=modules/erc20-helper/src/", "erc20/=modules/erc20/", "maple-proxy-factory/=modules/maple-proxy-factory/modules/proxy-factory/modules/ds-test/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"borrower_","type":"address"}],"name":"BorrowerAccepted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"CollateralPosted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount_","type":"uint256"},{"indexed":true,"internalType":"address","name":"destination_","type":"address"}],"name":"CollateralRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"lender_","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nextPaymentDueDate_","type":"uint256"}],"name":"Funded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount_","type":"uint256"},{"indexed":true,"internalType":"address","name":"destination_","type":"address"}],"name":"FundsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount_","type":"uint256"},{"indexed":true,"internalType":"address","name":"destination_","type":"address"}],"name":"FundsDrawnDown","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"FundsReturned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"borrower_","type":"address"},{"indexed":true,"internalType":"address","name":"feeManager_","type":"address"},{"indexed":false,"internalType":"address[2]","name":"assets_","type":"address[2]"},{"indexed":false,"internalType":"uint256[3]","name":"termDetails_","type":"uint256[3]"},{"indexed":false,"internalType":"uint256[3]","name":"amounts_","type":"uint256[3]"},{"indexed":false,"internalType":"uint256[4]","name":"rates_","type":"uint256[4]"},{"indexed":false,"internalType":"uint256[2]","name":"fees_","type":"uint256[2]"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"lender_","type":"address"}],"name":"LenderAccepted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"principalPaid_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interestPaid_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feesPaid_","type":"uint256"}],"name":"LoanClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"nextPaymentDueDate_","type":"uint256"}],"name":"LoanImpaired","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"refinanceCommitment_","type":"bytes32"},{"indexed":false,"internalType":"address","name":"refinancer_","type":"address"},{"indexed":false,"internalType":"uint256","name":"deadline_","type":"uint256"},{"indexed":false,"internalType":"bytes[]","name":"calls_","type":"bytes[]"}],"name":"NewTermsAccepted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"refinanceCommitment_","type":"bytes32"},{"indexed":false,"internalType":"address","name":"refinancer_","type":"address"},{"indexed":false,"internalType":"uint256","name":"deadline_","type":"uint256"},{"indexed":false,"internalType":"bytes[]","name":"calls_","type":"bytes[]"}],"name":"NewTermsProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"refinanceCommitment_","type":"bytes32"},{"indexed":false,"internalType":"address","name":"refinancer_","type":"address"},{"indexed":false,"internalType":"uint256","name":"deadline_","type":"uint256"},{"indexed":false,"internalType":"bytes[]","name":"calls_","type":"bytes[]"}],"name":"NewTermsRejected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"nextPaymentDueDate_","type":"uint256"}],"name":"NextPaymentDueDateRestored","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"principalPaid_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interestPaid_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fees_","type":"uint256"}],"name":"PaymentMade","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pendingBorrower_","type":"address"}],"name":"PendingBorrowerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pendingLender_","type":"address"}],"name":"PendingLenderSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"collateralRepossessed_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fundsRepossessed_","type":"uint256"},{"indexed":true,"internalType":"address","name":"destination_","type":"address"}],"name":"Repossessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token_","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount_","type":"uint256"},{"indexed":true,"internalType":"address","name":"destination_","type":"address"}],"name":"Skimmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"toVersion_","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"arguments_","type":"bytes"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"acceptBorrower","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"acceptLender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"refinancer_","type":"address"},{"internalType":"uint256","name":"deadline_","type":"uint256"},{"internalType":"bytes[]","name":"calls_","type":"bytes[]"}],"name":"acceptNewTerms","outputs":[{"internalType":"bytes32","name":"refinanceCommitment_","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"borrower","outputs":[{"internalType":"address","name":"borrower_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"closeLoan","outputs":[{"internalType":"uint256","name":"principal_","type":"uint256"},{"internalType":"uint256","name":"interest_","type":"uint256"},{"internalType":"uint256","name":"fees_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"closingRate","outputs":[{"internalType":"uint256","name":"closingRate_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateral","outputs":[{"internalType":"uint256","name":"collateral_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateralAsset","outputs":[{"internalType":"address","name":"collateralAsset_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateralRequired","outputs":[{"internalType":"uint256","name":"collateralRequired_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"drawableFunds","outputs":[{"internalType":"uint256","name":"drawableFunds_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"address","name":"destination_","type":"address"}],"name":"drawdownFunds","outputs":[{"internalType":"uint256","name":"collateralPosted_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"endingPrincipal","outputs":[{"internalType":"uint256","name":"endingPrincipal_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"excessCollateral","outputs":[{"internalType":"uint256","name":"excessCollateral_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"factory_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeManager","outputs":[{"internalType":"address","name":"feeManager_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"lender_","type":"address"}],"name":"fundLoan","outputs":[{"internalType":"uint256","name":"fundsLent_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fundsAsset","outputs":[{"internalType":"address","name":"fundsAsset_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"drawdown_","type":"uint256"}],"name":"getAdditionalCollateralRequiredFor","outputs":[{"internalType":"uint256","name":"collateral_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getClosingPaymentBreakdown","outputs":[{"internalType":"uint256","name":"principal_","type":"uint256"},{"internalType":"uint256","name":"interest_","type":"uint256"},{"internalType":"uint256","name":"fees_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNextPaymentBreakdown","outputs":[{"internalType":"uint256","name":"principal_","type":"uint256"},{"internalType":"uint256","name":"interest_","type":"uint256"},{"internalType":"uint256","name":"fees_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNextPaymentDetailedBreakdown","outputs":[{"internalType":"uint256","name":"principal_","type":"uint256"},{"internalType":"uint256[3]","name":"interest_","type":"uint256[3]"},{"internalType":"uint256[2]","name":"fees_","type":"uint256[2]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp_","type":"uint256"}],"name":"getRefinanceInterest","outputs":[{"internalType":"uint256","name":"proRataInterest_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset_","type":"address"}],"name":"getUnaccountedAmount","outputs":[{"internalType":"uint256","name":"unaccountedAmount_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globals","outputs":[{"internalType":"address","name":"globals_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governor","outputs":[{"internalType":"address","name":"governor_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gracePeriod","outputs":[{"internalType":"uint256","name":"gracePeriod_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"impairLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"implementation_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"interestRate","outputs":[{"internalType":"uint256","name":"interestRate_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isImpaired","outputs":[{"internalType":"bool","name":"isImpaired_","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lateFeeRate","outputs":[{"internalType":"uint256","name":"lateFeeRate_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lateInterestPremium","outputs":[{"internalType":"uint256","name":"lateInterestPremium_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lender","outputs":[{"internalType":"address","name":"lender_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"makePayment","outputs":[{"internalType":"uint256","name":"principal_","type":"uint256"},{"internalType":"uint256","name":"interest_","type":"uint256"},{"internalType":"uint256","name":"fees_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"migrator_","type":"address"},{"internalType":"bytes","name":"arguments_","type":"bytes"}],"name":"migrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nextPaymentDueDate","outputs":[{"internalType":"uint256","name":"nextPaymentDueDate_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"originalNextPaymentDueDate","outputs":[{"internalType":"uint256","name":"originalNextPaymentDueDate_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paymentInterval","outputs":[{"internalType":"uint256","name":"paymentInterval_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paymentsRemaining","outputs":[{"internalType":"uint256","name":"paymentsRemaining_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingBorrower","outputs":[{"internalType":"address","name":"pendingBorrower_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingLender","outputs":[{"internalType":"address","name":"pendingLender_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"postCollateral","outputs":[{"internalType":"uint256","name":"collateralPosted_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"principal","outputs":[{"internalType":"uint256","name":"principal_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"principalRequested","outputs":[{"internalType":"uint256","name":"principalRequested_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"refinancer_","type":"address"},{"internalType":"uint256","name":"deadline_","type":"uint256"},{"internalType":"bytes[]","name":"calls_","type":"bytes[]"}],"name":"proposeNewTerms","outputs":[{"internalType":"bytes32","name":"refinanceCommitment_","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"refinanceCommitment","outputs":[{"internalType":"bytes32","name":"refinanceCommitment_","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"refinanceInterest","outputs":[{"internalType":"uint256","name":"refinanceInterest_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"refinancer_","type":"address"},{"internalType":"uint256","name":"deadline_","type":"uint256"},{"internalType":"bytes[]","name":"calls_","type":"bytes[]"}],"name":"rejectNewTerms","outputs":[{"internalType":"bytes32","name":"refinanceCommitment_","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"address","name":"destination_","type":"address"}],"name":"removeCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"removeLoanImpairment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"destination_","type":"address"}],"name":"repossess","outputs":[{"internalType":"uint256","name":"collateralRepossessed_","type":"uint256"},{"internalType":"uint256","name":"fundsRepossessed_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"returnFunds","outputs":[{"internalType":"uint256","name":"fundsReturned_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation_","type":"address"}],"name":"setImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingBorrower_","type":"address"}],"name":"setPendingBorrower","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingLender_","type":"address"}],"name":"setPendingLender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token_","type":"address"},{"internalType":"address","name":"destination_","type":"address"}],"name":"skim","outputs":[{"internalType":"uint256","name":"skimmed_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"toVersion_","type":"uint256"},{"internalType":"bytes","name":"arguments_","type":"bytes"}],"name":"upgrade","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50614822806100206000396000f3fe608060405234801561001057600080fd5b50600436106103835760003560e01c80637c3a00fd116101de578063ba5d30781161010f578063d05951a0116100ad578063d4754d5f1161007c578063d4754d5f146106a8578063d784d426146106b0578063d8dfeb45146106c3578063e48f6faf146106cb57600080fd5b8063d05951a01461065a578063d0fb02031461066d578063d3bcd5e21461067e578063d41ddc961461069557600080fd5b8063c3124525116100e9578063c312452514610624578063c3fbb6fd1461062c578063c45a01551461063f578063ccc044841461064757600080fd5b8063ba5d307814610603578063ba83276b1461060b578063bcead63e1461061357600080fd5b8063a29d7aab1161017c578063acb522b411610156578063acb522b4146105d8578063b86a513e146105eb578063b96b5c99146105f3578063b9b1f4e3146105fb57600080fd5b8063a29d7aab146105ac578063a97d1161146105bf578063aabaecd6146105c757600080fd5b80638ffc9215116101b85780638ffc92151461058157806396663914146105895780639e10320b14610591578063a06db7dc146105a457600080fd5b80637c3a00fd146105555780637df1f1b91461055d57806387accaf11461056e57600080fd5b806345755dd6116102b85780636174b27211610256578063712b772f11610230578063712b772f1461052a57806375a206761461053d57806377b3c55c146105455780637a0e6fa11461054d57600080fd5b80636174b272146104f3578063700f50061461050657806370a10c891461051757600080fd5b806350f2012f1161029257806350f2012f146104995780635114cb52146104ac5780635c60da1b146104da5780635eeb53b4146104e257600080fd5b806345755dd61461044b57806347350e9f1461045e5780634eac42351461048657600080fd5b8063227000371161032557806339ba9f86116102ff57806339ba9f861461041757806339d65834146104285780633b99bcee146104305780634003f34d1461044357600080fd5b806322700037146103f4578063267f4ac3146103fc5780632ead10981461040f57600080fd5b80630fe3d9b7116103615780630fe3d9b7146103c9578063144ee4b5146103d15780631cc1cf46146103d95780631f3f19ab146103e157600080fd5b806301daa38f146103885780630895326f146103925780630c340a24146103a9575b600080fd5b6103906106de565b005b6013545b6040519081526020015b60405180910390f35b6103b161081d565b6040516001600160a01b0390911681526020016103a0565b61039061089c565b6103906109d4565b600754610396565b6103906103ef366004614266565b610aec565b601a54610396565b61039061040a366004614266565b610cee565b600b54610396565b6005546001600160a01b03166103b1565b600954610396565b61039061043e366004614433565b610d8a565b601254610396565b6103966104593660046143dc565b610fa0565b61047161046c366004614266565b61110a565b604080519283526020830191909152016103a0565b6103966104943660046143dc565b6112fb565b6103966104a73660046143dc565b611343565b6104bf6104ba3660046143dc565b6114a4565b604080519384526020840192909252908201526060016103a0565b6103b1611ae4565b6003546001600160a01b03166103b1565b610396610501366004614266565b611aee565b6002546001600160a01b03166103b1565b61039661052536600461432e565b611bc2565b6103966105383660046142a0565b6120d6565b600c54610396565b600a54610396565b61039661220d565b600854610396565b6000546001600160a01b03166103b1565b61039661057c36600461432e565b612249565b600d54610396565b6104bf6123e6565b61039661059f3660046143dc565b6124e3565b600654610396565b601a5460405190151581526020016103a0565b601654610396565b6004546001600160a01b03166103b1565b6103966105e636600461432e565b612506565b600e54610396565b6104bf612699565b600f54610396565b601454610396565b601554610396565b6001546001600160a01b03166103b1565b6103b1612715565b61039061063a3660046142d9565b612757565b6103b16127fc565b61039661065536600461440e565b612806565b6104bf6106683660046143dc565b612a48565b6019546001600160a01b03166103b1565b61068661306b565b6040516103a093929190614659565b6103906106a336600461440e565b6130aa565b61039061329b565b6103906106be366004614266565b61333f565b601154610396565b6103966106d9366004614266565b6133cb565b6106e6612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b15801561071e57600080fd5b505afa158015610732573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061075691906143ba565b1561077c5760405162461bcd60e51b81526004016107739061462e565b60405180910390fd5b6002546001600160a01b031633146107d65760405162461bcd60e51b815260206004820152601a60248201527f4d4c3a41423a4e4f545f50454e44494e475f424f52524f5745520000000000006044820152606401610773565b600280546001600160a01b031990811690915560008054339216821781556040517f29bac0ac2b15405bfcc160bb74b6ae7a559b7674ce33db80785ada73e38204d29190a2565b6000610827612715565b6001600160a01b0316630c340a246040518163ffffffff1660e01b815260040160206040518083038186803b15801561085f57600080fd5b505afa158015610873573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108979190614283565b905090565b6108a4612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b1580156108dc57600080fd5b505afa1580156108f0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091491906143ba565b156109315760405162461bcd60e51b81526004016107739061462e565b6003546001600160a01b0316331461098b5760405162461bcd60e51b815260206004820152601860248201527f4d4c3a414c3a4e4f545f50454e44494e475f4c454e44455200000000000000006044820152606401610773565b600380546001600160a01b031990811690915560018054339216821790556040517fd6165838d2e3db87aa1002b548048673fc6427eefbd1b914e100f3a0deae23e390600090a2565b601a546001546001600160a01b03163314610a255760405162461bcd60e51b815260206004820152601160248201527026a61d2926249d2727aa2fa622a72222a960791b6044820152606401610773565b80610a685760405162461bcd60e51b815260206004820152601360248201527213530e9493124e9393d517d253541052549151606a1b6044820152606401610773565b80421115610aab5760405162461bcd60e51b815260206004820152601060248201526f4d4c3a524c493a504153545f4441544560801b6044820152606401610773565b60128190556000601a556040518181527f962d5a38dc48af765ecb4f177a88713b592b5bf59e64f497ab33af13b7c0e9de906020015b60405180910390a150565b610af4612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b158015610b2c57600080fd5b505afa158015610b40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6491906143ba565b15610b815760405162461bcd60e51b81526004016107739061462e565b6000546001600160a01b03163314610bd15760405162461bcd60e51b815260206004820152601360248201527226a61d29a8211d2727aa2fa127a92927aba2a960691b6044820152606401610773565b610bd9612715565b60405163eaf6e48360e01b81526001600160a01b038381166004830152919091169063eaf6e4839060240160206040518083038186803b158015610c1c57600080fd5b505afa158015610c30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5491906143ba565b610ca05760405162461bcd60e51b815260206004820152601760248201527f4d4c3a5350423a494e56414c49445f424f52524f5745520000000000000000006044820152606401610773565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527f10f06072822ef73860fedb88933f968d20bb4aadce8a8d360d1124cb6ce1e0b290602001610ae1565b6001546001600160a01b03163314610d3c5760405162461bcd60e51b815260206004820152601160248201527026a61d29a8261d2727aa2fa622a72222a960791b6044820152606401610773565b600380546001600160a01b0319166001600160a01b0383169081179091556040519081527fa3ab02442c80a4102475683f16513c9139a89142be9db9804edfcfbb379fc49290602001610ae1565b610d92612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b158015610dca57600080fd5b505afa158015610dde573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e0291906143ba565b15610e1f5760405162461bcd60e51b81526004016107739061462e565b610e27612715565b6001600160a01b031663be7c13f76040518163ffffffff1660e01b815260040160206040518083038186803b158015610e5f57600080fd5b505afa158015610e73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e979190614283565b6001600160a01b0316336001600160a01b031614610ef75760405162461bcd60e51b815260206004820152601760248201527f4d4c3a553a4e4f545f53454355524954595f41444d494e0000000000000000006044820152606401610773565b7faaaa7ee6b0c2f4ee1fa7312c7d5b3623a434da5a1a9ce3cb6e629caa23454ab6838383604051610f2a939291906146ba565b60405180910390a1610f3a6138ac565b6001600160a01b031663fe69f7088484846040518463ffffffff1660e01b8152600401610f69939291906146ba565b600060405180830381600087803b158015610f8357600080fd5b505af1158015610f97573d6000803e3d6000fd5b50505050505050565b6000610faa612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b158015610fe257600080fd5b505afa158015610ff6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061101a91906143ba565b156110375760405162461bcd60e51b81526004016107739061462e565b8115806110575750600554611057906001600160a01b03163330856138db565b6110a35760405162461bcd60e51b815260206004820152601a60248201527f4d4c3a52463a5452414e534645525f46524f4d5f4641494c45440000000000006044820152606401610773565b6005546110b8906001600160a01b0316611aee565b905080600f60008282546110cc919061471b565b90915550506040518181527f278e51d3323fbf18b9fb8df3f8b97e31b145bc1146c52e764cf4aa1bfc4ba17d906020015b60405180910390a1919050565b60015460009081906001600160a01b0316331461115b5760405162461bcd60e51b815260206004820152600f60248201526e26a61d291d2727aa2fa622a72222a960891b6044820152606401610773565b60125480158015906111785750600654611175908261471b565b42115b6111ba5760405162461bcd60e51b815260206004820152601360248201527213530e948e9393d517d25397d1115190555315606a1b6044820152606401610773565b6111c2613952565b60006011819055600f8190556004546001600160a01b0316906111e482611aee565b94508414806111f957506111f981868661398b565b61123e5760405162461bcd60e51b815260206004820152601660248201527513530e948e90d7d514905394d1915497d1905253115160521b6044820152606401610773565b6005546001600160a01b0316600061125582611aee565b945084148061126a575061126a81878661398b565b6112af5760405162461bcd60e51b815260206004820152601660248201527513530e948e9197d514905394d1915497d1905253115160521b6044820152606401610773565b60408051868152602081018690526001600160a01b038816917f027e623aab0b174da270ff529cad1c54f09182651e07437d2ac557929b9e5b49910160405180910390a2505050915091565b60008061131d60145484600f546113129190614774565b600d54600c546139c8565b60115490915080821161133157600061133b565b61133b8183614774565b949350505050565b600061134d612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b15801561138557600080fd5b505afa158015611399573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113bd91906143ba565b156113da5760405162461bcd60e51b81526004016107739061462e565b8115806113fa57506004546113fa906001600160a01b03163330856138db565b6114465760405162461bcd60e51b815260206004820152601a60248201527f4d4c3a50433a5452414e534645525f46524f4d5f4641494c45440000000000006044820152606401610773565b60045461145b906001600160a01b0316611aee565b9050806011600082825461146f919061471b565b90915550506040518181527f437d44b2c697fb69e2b2f25f57fd844e376c25ed28ed5a9c4be88aa1e5c87d12906020016110fd565b60008054819081906001600160a01b03163314156117a7576114c4612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b1580156114fc57600080fd5b505afa158015611510573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153491906143ba565b156115515760405162461bcd60e51b81526004016107739061462e565b8315806115715750600554611571906001600160a01b03163330876138db565b6115bd5760405162461bcd60e51b815260206004820152601a60248201527f4d4c3a4d503a5452414e534645525f46524f4d5f4641494c45440000000000006044820152606401610773565b6115c5613a18565b6115cd612699565b506000601681905591945092506115e4838561471b565b60055490915081906115fe906001600160a01b0316611aee565b600f5461160b919061471b565b6116159190614774565b600f556116226001613a28565b60135460125491935090600060018314156116445761163f613952565b611681565b600754611651908361471b565b905080601281905550866014600082825461166c9190614774565b9091555061167d9050600184614774565b6013555b60408051888152602081018890529081018690527fcf358e925a8e033c6db877f18d10df6f21cd04ef165537bad5fc814eb23af9609060600160405180910390a16005546001546116df916001600160a01b0390811691168661398b565b6116fb5760405162461bcd60e51b8152600401610773906145ff565b60015460405163b5add71760e01b8152600481018990526024810188905260448101849052606481018390526001600160a01b039091169063b5add71790608401600060405180830381600087803b15801561175657600080fd5b505af115801561176a573d6000803e3d6000fd5b50506001546040518781526001600160a01b0390911692506000805160206147cd833981519152915060200160405180910390a250505050611add565b600f546117b2612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b1580156117ea57600080fd5b505afa1580156117fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061182291906143ba565b1561183f5760405162461bcd60e51b81526004016107739061462e565b84158061185f575060055461185f906001600160a01b03163330886138db565b6118ab5760405162461bcd60e51b815260206004820152601a60248201527f4d4c3a4d503a5452414e534645525f46524f4d5f4641494c45440000000000006044820152606401610773565b6118b3613a18565b6118bb612699565b506000601681905591955093506118d2848661471b565b60055490915081906118ec906001600160a01b0316611aee565b600f546118f9919061471b565b6119039190614774565b600f556119106001613a28565b60135460125491945090600060018314156119325761192d613952565b61196f565b60075461193f908361471b565b905080601281905550876014600082825461195a9190614774565b9091555061196b9050600184614774565b6013555b60408051898152602081018990529081018790527fcf358e925a8e033c6db877f18d10df6f21cd04ef165537bad5fc814eb23af9609060600160405180910390a16005546001546119cd916001600160a01b0390811691168661398b565b6119e95760405162461bcd60e51b8152600401610773906145ff565b60015460405163b5add71760e01b8152600481018a90526024810189905260448101849052606481018390526001600160a01b039091169063b5add71790608401600060405180830381600087803b158015611a4457600080fd5b505af1158015611a58573d6000803e3d6000fd5b50506001546040518781526001600160a01b0390911692506000805160206147cd833981519152915060200160405180910390a25050505080600f541015611adb5760405162461bcd60e51b81526020600482015260166024820152754d4c3a43414e4e4f545f5553455f4452415741424c4560501b6044820152606401610773565b505b9193909250565b6000610897613c0a565b6005546000906001600160a01b03838116911614611b0d576000611b11565b600f545b6004546001600160a01b03848116911614611b2d576000611b31565b6011545b6040516370a0823160e01b81523060048201526001600160a01b038516906370a082319060240160206040518083038186803b158015611b7057600080fd5b505afa158015611b84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba891906143f5565b611bb29190614774565b611bbc9190614774565b92915050565b6001546000906001600160a01b03163314611c135760405162461bcd60e51b815260206004820152601160248201527026a61d20a72a1d2727aa2fa622a72222a960791b6044820152606401610773565b611c1f85858585613c34565b90508060155414611c725760405162461bcd60e51b815260206004820152601a60248201527f4d4c3a414e543a434f4d4d49544d454e545f4d49534d415443480000000000006044820152606401610773565b6001600160a01b0385163b611cc95760405162461bcd60e51b815260206004820152601960248201527f4d4c3a414e543a494e56414c49445f524546494e414e434552000000000000006044820152606401610773565b83421115611d195760405162461bcd60e51b815260206004820152601960248201527f4d4c3a414e543a455850495245445f434f4d4d49544d454e54000000000000006044820152606401610773565b600754601254600d54600082611d2f854261471b565b10611d4d57611d3e8484614774565b611d489042614774565b611d50565b60005b6019546040516341a703bb60e01b815260048101859052602481018390529192506001600160a01b03169081906341a703bb90604401600060405180830381600087803b158015611da057600080fd5b505af1158015611db4573d6000803e3d6000fd5b505050506000611dc3426124e3565b90508060166000828254611dd7919061471b565b9091555050600060158190555b88811015611eb45760008c6001600160a01b03168b8b84818110611e0a57611e0a6147a1565b9050602002810190611e1c91906146d4565b604051611e2a929190614553565b600060405180830381855af49150503d8060008114611e65576040519150601f19603f3d011682016040523d82523d6000602084013e611e6a565b606091505b5050905080611eab5760405162461bcd60e51b815260206004820152600d60248201526c13530e9053950e919052531151609a1b6044820152606401610773565b50600101611de4565b507f7150c332bd889236b6ab42cc34f0853631ceb58827f58a8697b682f13e390a8c878c8c8c8c604051611eec9594939291906145c6565b60405180910390a1600554600d5460075497506001600160a01b0390911690611f15884261471b565b601255611f20613a18565b6040516377cf0ddb60e11b815260048101829052602481018990526001600160a01b0385169063ef9e1bb690604401600060405180830381600087803b158015611f6957600080fd5b505af1158015611f7d573d6000803e3d6000fd5b50506040516327d180b560e01b81526001600160a01b03858116600483015260248201859052871692506327d180b59150604401602060405180830381600087803b158015611fcb57600080fd5b505af1158015611fdf573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061200391906143f5565b600f60008282546120149190614774565b909155506120229050613c6d565b61206e5760405162461bcd60e51b815260206004820152601e60248201527f4d4c3a414e543a494e53554646494349454e545f434f4c4c41544552414c00006044820152606401610773565b600061207983611aee565b146120c65760405162461bcd60e51b815260206004820152601760248201527f4d4c3a414e543a554e45585045435445445f46554e44530000000000000000006044820152606401610773565b5050505050505050949350505050565b60006120e0612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b15801561211857600080fd5b505afa15801561212c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061215091906143ba565b1561216d5760405162461bcd60e51b81526004016107739061462e565b816001600160a01b0316836001600160a01b03167ff1f6a55e7ad487ac8dd8e1d4517348d3b410a7a0bc405ef87b09078dc51b23b66121ab86611aee565b60405181815290945060200160405180910390a36121ca83838361398b565b611bbc5760405162461bcd60e51b815260206004820152601460248201527313530e94ce9514905394d1915497d1905253115160621b6044820152606401610773565b600080612224601454600f54600d54600c546139c8565b601154909150818111612238576000612242565b6122428282614774565b9250505090565b6000612253612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b15801561228b57600080fd5b505afa15801561229f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122c391906143ba565b156122e05760405162461bcd60e51b81526004016107739061462e565b6000546001600160a01b031633146123305760405162461bcd60e51b815260206004820152601360248201527226a61d28272a1d2727aa2fa127a92927aba2a960691b6044820152606401610773565b428410156123805760405162461bcd60e51b815260206004820152601760248201527f4d4c3a504e543a494e56414c49445f444541444c494e450000000000000000006044820152606401610773565b7ff94d2f0322894aaf1bce14561461a8b8b6c9b11a77bbe80f20b804da8a95e4b7826123ad5760006123b9565b6123b986868686613c34565b6015819055915081868686866040516123d69594939291906145c6565b60405180910390a1949350505050565b60195460135460405163e0b58e0d60e01b815230600482015260248101919091526000918291829182918291829182916001600160a01b03169063e0b58e0d9060440160806040518083038186803b15801561244157600080fd5b505afa158015612455573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124799190614466565b93509350935093508083838661248f919061471b565b612499919061471b565b6124a3919061471b565b9450601654670de0b6b3a76400006009546014549950896124c49190614755565b6124ce9190614733565b6124d8919061471b565b955050505050909192565b6000611bbc82600754601454600e54600854601354601254600a54600b54613c8d565b6000612510612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b15801561254857600080fd5b505afa15801561255c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061258091906143ba565b1561259d5760405162461bcd60e51b81526004016107739061462e565b6000546001600160a01b03163314806125c057506001546001600160a01b031633145b6125fd5760405162461bcd60e51b815260206004820152600e60248201526d09a9874a49ca8749c9ebe82aaa8960931b6044820152606401610773565b61260985858585613c34565b9050806015541461265c5760405162461bcd60e51b815260206004820152601a60248201527f4d4c3a524e543a434f4d4d49544d454e545f4d49534d415443480000000000006044820152606401610773565b60006015556040517f47244a449377da5fd10e98d86d118dee442e842fc34f05179c973cfcff6acba7906123d690839088908890889088906145c6565b60008060006126a66141e1565b6126ae6141ff565b6126cf42601254600754601454600e54601354600854600a54600b54613cfa565b604082015160208301518351949950929550909350916126ef919061471b565b6126f9919061471b565b6020820151825191955061270c9161471b565b92505050909192565b600061271f6138ac565b6001600160a01b0316633a60339a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561085f57600080fd5b61275f6138ac565b6001600160a01b0316336001600160a01b0316146127b25760405162461bcd60e51b815260206004820152601060248201526f4d4c3a4d3a4e4f545f464143544f525960801b6044820152606401610773565b6127bd838383613e17565b6127f75760405162461bcd60e51b815260206004820152600b60248201526a13530e934e91905253115160aa1b6044820152606401610773565b505050565b60006108976138ac565b6000612810612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b15801561284857600080fd5b505afa15801561285c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061288091906143ba565b1561289d5760405162461bcd60e51b81526004016107739061462e565b6000546001600160a01b031633146128ec5760405162461bcd60e51b815260206004820152601260248201527126a61d22231d2727aa2fa127a92927aba2a960711b6044820152606401610773565b816001600160a01b03167f7578fe8c4d9f6fc38fdad20d219b0ce47d38bbf8a72bdb26867809f24119363d8460405161292791815260200190565b60405180910390a2600061293a846112fb565b9050801561297b5760045460009061295a906001600160a01b0316611aee565b905061297781831161296d576000611343565b6104a78284614774565b9250505b83600f600082825461298d9190614774565b90915550506005546129a9906001600160a01b0316848661398b565b6129ed5760405162461bcd60e51b815260206004820152601560248201527413530e91118e9514905394d1915497d19052531151605a1b6044820152606401610773565b6129f5613c6d565b612a415760405162461bcd60e51b815260206004820152601d60248201527f4d4c3a44463a494e53554646494349454e545f434f4c4c41544552414c0000006044820152606401610773565b5092915050565b60008054819081906001600160a01b0316331415612d4157612a68612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b158015612aa057600080fd5b505afa158015612ab4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad891906143ba565b15612af55760405162461bcd60e51b81526004016107739061462e565b831580612b155750600554612b15906001600160a01b03163330876138db565b612b615760405162461bcd60e51b815260206004820152601a60248201527f4d4c3a434c3a5452414e534645525f46524f4d5f4641494c45440000000000006044820152606401610773565b60125442811015612bac5760405162461bcd60e51b81526020600482015260156024820152744d4c3a434c3a5041594d454e545f49535f4c41544560581b6044820152606401610773565b612bb4613a18565b612bbc6123e6565b50600060168190559195509350612bd3848661471b565b6005549091508190612bed906001600160a01b0316611aee565b600f54612bfa919061471b565b612c049190614774565b600f55601354612c1390613a28565b9250612c1d613952565b60408051868152602081018690529081018490527f4acb957de3799dd3d95bb7da6bcfbca6f5a33812d69ad37816ed87e79b6327d69060600160405180910390a1600554600154612c7b916001600160a01b0390811691168361398b565b612c975760405162461bcd60e51b8152600401610773906145ff565b60015460405163b5add71760e01b8152600481018790526024810186905260448101849052600060648201526001600160a01b039091169063b5add71790608401600060405180830381600087803b158015612cf257600080fd5b505af1158015612d06573d6000803e3d6000fd5b50506001546040518481526001600160a01b0390911692506000805160206147cd833981519152915060200160405180910390a25050611add565b600f54612d4c612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b158015612d8457600080fd5b505afa158015612d98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dbc91906143ba565b15612dd95760405162461bcd60e51b81526004016107739061462e565b841580612df95750600554612df9906001600160a01b03163330886138db565b612e455760405162461bcd60e51b815260206004820152601a60248201527f4d4c3a434c3a5452414e534645525f46524f4d5f4641494c45440000000000006044820152606401610773565b60125442811015612e905760405162461bcd60e51b81526020600482015260156024820152744d4c3a434c3a5041594d454e545f49535f4c41544560581b6044820152606401610773565b612e98613a18565b612ea06123e6565b50600060168190559196509450612eb7858761471b565b6005549091508190612ed1906001600160a01b0316611aee565b600f54612ede919061471b565b612ee89190614774565b600f55601354612ef790613a28565b9350612f01613952565b60408051878152602081018790529081018590527f4acb957de3799dd3d95bb7da6bcfbca6f5a33812d69ad37816ed87e79b6327d69060600160405180910390a1600554600154612f5f916001600160a01b0390811691168361398b565b612f7b5760405162461bcd60e51b8152600401610773906145ff565b60015460405163b5add71760e01b8152600481018890526024810187905260448101849052600060648201526001600160a01b039091169063b5add71790608401600060405180830381600087803b158015612fd657600080fd5b505af1158015612fea573d6000803e3d6000fd5b50506001546040518481526001600160a01b0390911692506000805160206147cd833981519152915060200160405180910390a2505080600f541015611adb5760405162461bcd60e51b81526020600482015260166024820152754d4c3a43414e4e4f545f5553455f4452415741424c4560501b6044820152606401610773565b60006130756141e1565b61307d6141ff565b61309e42601254600754601454600e54601354600854600a54600b54613cfa565b91959094509092509050565b6130b2612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b1580156130ea57600080fd5b505afa1580156130fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061312291906143ba565b1561313f5760405162461bcd60e51b81526004016107739061462e565b6000546001600160a01b0316331461318e5760405162461bcd60e51b815260206004820152601260248201527126a61d29219d2727aa2fa127a92927aba2a960711b6044820152606401610773565b806001600160a01b03167f97b446ee2df422b7273fe6d658674835f9de3319d131c229f9a2f8ed62a76193836040516131c991815260200190565b60405180910390a281601160008282546131e39190614774565b90915550506004546131ff906001600160a01b0316828461398b565b6132435760405162461bcd60e51b815260206004820152601560248201527413530e9490ce9514905394d1915497d19052531151605a1b6044820152606401610773565b61324b613c6d565b6132975760405162461bcd60e51b815260206004820152601d60248201527f4d4c3a52433a494e53554646494349454e545f434f4c4c41544552414c0000006044820152606401610773565b5050565b6012546001546001600160a01b031633146132eb5760405162461bcd60e51b815260206004820152601060248201526f26a61d24a61d2727aa2fa622a72222a960811b6044820152606401610773565b60008142116132fa57426132fc565b815b90507f54c4bb2a061eac3afc1daf65bd7a75a0cdb4ac02824757f40019dff2da5849358160405161332f91815260200190565b60405180910390a1601255601a55565b6133476138ac565b6001600160a01b0316336001600160a01b03161461339b5760405162461bcd60e51b81526020600482015260116024820152704d4c3a53493a4e4f545f464143544f525960781b6044820152606401610773565b6001600160a01b03167f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b50565b600180546001600160a01b0319166001600160a01b03831690811790915560009061342f5760405162461bcd60e51b815260206004820152601460248201527326a61d23261d24a72b20a624a22fa622a72222a960611b6044820152606401610773565b6000826001600160a01b031663c45a01556040518163ffffffff1660e01b815260040160206040518083038186803b15801561346a57600080fd5b505afa15801561347e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134a29190614283565b90506134ac612715565b604051636167f93160e01b81526b2627a0a72fa6a0a720a3a2a960a11b60048201526001600160a01b0383811660248301529190911690636167f9319060440160206040518083038186803b15801561350457600080fd5b505afa158015613518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353c91906143ba565b6135805760405162461bcd60e51b81526020600482015260156024820152744d4c3a464c3a494e56414c49445f464143544f525960581b6044820152606401610773565b6040516335a2735f60e11b81526001600160a01b038481166004830152821690636b44e6be9060240160206040518083038186803b1580156135c157600080fd5b505afa1580156135d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135f991906143ba565b61363e5760405162461bcd60e51b81526020600482015260166024820152754d4c3a464c3a494e56414c49445f494e5354414e434560501b6044820152606401610773565b60125415801561364f575060135415155b61368f5760405162461bcd60e51b81526020600482015260116024820152704d4c3a464c3a4c4f414e5f41435449564560781b6044820152606401610773565b600554600754600d546019546001600160a01b03938416936136b691859116600019613e90565b6136f75760405162461bcd60e51b815260206004820152601260248201527113530e91930e9054141493d59157d190525360721b6044820152606401610773565b6019546040516377cf0ddb60e11b815260048101839052602481018490526001600160a01b039091169063ef9e1bb690604401600060405180830381600087803b15801561374457600080fd5b505af1158015613758573d6000803e3d6000fd5b50506019546040516327d180b560e01b81526001600160a01b038781166004830152602482018690526000945090911691506327d180b590604401602060405180830381600087803b1580156137ad57600080fd5b505af11580156137c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137e591906143f5565b90506137f18183614774565b600f5560006137ff85611aee565b146138455760405162461bcd60e51b81526020600482015260166024820152754d4c3a464c3a554e45585045435445445f46554e445360501b6044820152606401610773565b866001600160a01b03167fcd909ec339185c4598a4096e174308fbdf136d117f230960f873a2f2e81f63af8360148190559750878542613885919061471b565b60128190556040805192835260208301919091520160405180910390a25050505050919050565b60006138d67f7a45a402e4cb6e08ebc196f20f66d5d30e67285a2a8aa80503fa409e727a4af15490565b919050565b6040516001600160a01b03808516602483015283166044820152606481018290526000906139499086906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613f0c565b95945050505050565b60006006819055600781905560088190556009819055600a819055600b819055600e819055601281905560138190556014819055601a55565b6040516001600160a01b0383166024820152604481018290526000906139be90859063a9059cbb60e01b90606401613912565b90505b9392505050565b600083851115613a0d57826001816139e08789614774565b6139ea9086614755565b6139f4919061471b565b6139fe9190614774565b613a089190614733565b613949565b506000949350505050565b601a54613a2157565b6000601a55565b6005546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a082319060240160206040518083038186803b158015613a7057600080fd5b505afa158015613a84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613aa891906143f5565b6019546005546040516376bd6e5160e01b81526001600160a01b0391821660048201526024810187905292935016906376bd6e5190604401602060405180830381600087803b158015613afa57600080fd5b505af1158015613b0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b3291906143f5565b506005546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b158015613b7757600080fd5b505afa158015613b8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613baf91906143f5565b905080821115613be257613bc38183614774565b925082600f6000828254613bd79190614774565b90915550613c039050565b613bec8282614774565b600f6000828254613bfd919061471b565b90915550505b5050919050565b60006138d67f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b600084848484604051602001613c4d949392919061459e565b604051602081830303815290604052805190602001209050949350505050565b6000613c83601454600f54600d54600c546139c8565b6011541015905090565b600083613c9a8a8c61471b565b1015613ca857506000613ced565b6000613cb48a86614774565b613cbe908c614774565b9050613ccd898989848a613fac565b9250613cdf90508b8a8988888861409f565b613ce9908361471b565b9150505b9998505050505050505050565b6000613d046141e1565b613d0c6141ff565b613d198989888d8b613fac565b8352925060018714613d2b5782613d2d565b885b9250613d3d8c8a888e898961409f565b8260016020020152601654826002602002015260195460405163e0b58e0d60e01b8152306004820152600160248201526000918291829182916001600160a01b039091169063e0b58e0d9060440160806040518083038186803b158015613da357600080fd5b505afa158015613db7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ddb9190614466565b93509350935093508284613def919061471b565b8552613dfb818361471b565b602086015250949e939d50919b50919950505050505050505050565b6000833b80613e2a5760009150506139c1565b846001600160a01b03168484604051613e44929190614553565b600060405180830381855af49150503d8060008114613e7f576040519150601f19603f3d011682016040523d82523d6000602084013e613e84565b606091505b50909695505050505050565b6040516001600160a01b038316602482015260006044820181905290613ec390859063095ea7b360e01b90606401613912565b613ecf575060006139c1565b81613edc575060016139c1565b6040516001600160a01b0384166024820152604481018390526139be90859063095ea7b360e01b90606401613912565b60006001600160a01b0383163b613f2557506000611bbc565b6060836001600160a01b031683604051613f3f9190614563565b6000604051808303816000865af19150503d8060008114613f7c576040519150601f19603f3d011682016040523d82523d6000602084013e613f81565b606091505b50909250905081801561133b57508051158061133b57508080602001905181019061133b91906143ba565b6000806000613fbb868661413b565b90506000613fe3613fd483670de0b6b3a764000061471b565b86670de0b6b3a7640000614156565b9050670de0b6b3a764000081116140165784613fff898b614774565b6140099190614733565b6000935093505050614095565b600061402a670de0b6b3a764000083614774565b838a670de0b6b3a764000061403f868f614755565b6140499190614733565b6140539190614774565b61405d9190614755565b6140679190614733565b90506140748a89896141b8565b93508381101561408557600061408f565b61408f8482614774565b94505050505b9550959350505050565b60008387116140b057506000614131565b6000620151806140c0868a614774565b6140cd906201517f61471b565b6140d79190614733565b6140e49062015180614755565b90506140fa876140f4858961471b565b836141b8565b614104908361471b565b9150670de0b6b3a76400006141198886614755565b6141239190614733565b61412d908361471b565b9150505b9695505050505050565b60006301e1338061414c8385614755565b6139c19190614733565b6000600183166141665781614168565b835b90505b60019290921c9182156139c157816141838580614755565b61418d9190614733565b93506001831661419c5761416b565b816141a78583614755565b6141b19190614733565b905061416b565b6000670de0b6b3a76400006141cd848461413b565b6141d79086614755565b6139be9190614733565b60405180606001604052806003906020820280368337509192915050565b60405180604001604052806002906020820280368337509192915050565b60008083601f84011261422f57600080fd5b50813567ffffffffffffffff81111561424757600080fd5b60208301915083602082850101111561425f57600080fd5b9250929050565b60006020828403121561427857600080fd5b81356139c1816147b7565b60006020828403121561429557600080fd5b81516139c1816147b7565b600080604083850312156142b357600080fd5b82356142be816147b7565b915060208301356142ce816147b7565b809150509250929050565b6000806000604084860312156142ee57600080fd5b83356142f9816147b7565b9250602084013567ffffffffffffffff81111561431557600080fd5b6143218682870161421d565b9497909650939450505050565b6000806000806060858703121561434457600080fd5b843561434f816147b7565b935060208501359250604085013567ffffffffffffffff8082111561437357600080fd5b818701915087601f83011261438757600080fd5b81358181111561439657600080fd5b8860208260051b85010111156143ab57600080fd5b95989497505060200194505050565b6000602082840312156143cc57600080fd5b815180151581146139c157600080fd5b6000602082840312156143ee57600080fd5b5035919050565b60006020828403121561440757600080fd5b5051919050565b6000806040838503121561442157600080fd5b8235915060208301356142ce816147b7565b60008060006040848603121561444857600080fd5b83359250602084013567ffffffffffffffff81111561431557600080fd5b6000806000806080858703121561447c57600080fd5b505082516020840151604085015160609095015191969095509092509050565b818352600060208085019450848460051b86018460005b8781101561451d5783830389528135601e198836030181126144d457600080fd5b8701803567ffffffffffffffff8111156144ed57600080fd5b8036038913156144fc57600080fd5b614509858289850161452a565b9a87019a94505050908401906001016144b3565b5090979650505050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8183823760009101908152919050565b6000825160005b81811015614584576020818601810151858301520161456a565b81811115614593576000828501525b509190910192915050565b60018060a01b038516815283602082015260606040820152600061413160608301848661449c565b85815260018060a01b03851660208201528360408201526080606082015260006145f460808301848661449c565b979650505050505050565b60208082526015908201527413530e93540e9514905394d1915497d19052531151605a1b604082015260600190565b602080825260119082015270130e941493d513d0d3d317d4105554d151607a1b604082015260600190565b83815260c0810160208083018560005b600381101561468657815183529183019190830190600101614669565b505050608083018460005b60028110156146ae57815183529183019190830190600101614691565b50505050949350505050565b83815260406020820152600061394960408301848661452a565b6000808335601e198436030181126146eb57600080fd5b83018035915067ffffffffffffffff82111561470657600080fd5b60200191503681900382131561425f57600080fd5b6000821982111561472e5761472e61478b565b500190565b60008261475057634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561476f5761476f61478b565b500290565b6000828210156147865761478661478b565b500390565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6001600160a01b03811681146133c857600080fdfe6bd56533ce1c8ea03f7b858ac441b5a86d140a793a7c9e3faecbbe517c2c8791a26469706673582212204a309c37cbae06ae4046df36b05aa1ac996ec534c14d5709848916960b7ff5da64736f6c63430008070033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103835760003560e01c80637c3a00fd116101de578063ba5d30781161010f578063d05951a0116100ad578063d4754d5f1161007c578063d4754d5f146106a8578063d784d426146106b0578063d8dfeb45146106c3578063e48f6faf146106cb57600080fd5b8063d05951a01461065a578063d0fb02031461066d578063d3bcd5e21461067e578063d41ddc961461069557600080fd5b8063c3124525116100e9578063c312452514610624578063c3fbb6fd1461062c578063c45a01551461063f578063ccc044841461064757600080fd5b8063ba5d307814610603578063ba83276b1461060b578063bcead63e1461061357600080fd5b8063a29d7aab1161017c578063acb522b411610156578063acb522b4146105d8578063b86a513e146105eb578063b96b5c99146105f3578063b9b1f4e3146105fb57600080fd5b8063a29d7aab146105ac578063a97d1161146105bf578063aabaecd6146105c757600080fd5b80638ffc9215116101b85780638ffc92151461058157806396663914146105895780639e10320b14610591578063a06db7dc146105a457600080fd5b80637c3a00fd146105555780637df1f1b91461055d57806387accaf11461056e57600080fd5b806345755dd6116102b85780636174b27211610256578063712b772f11610230578063712b772f1461052a57806375a206761461053d57806377b3c55c146105455780637a0e6fa11461054d57600080fd5b80636174b272146104f3578063700f50061461050657806370a10c891461051757600080fd5b806350f2012f1161029257806350f2012f146104995780635114cb52146104ac5780635c60da1b146104da5780635eeb53b4146104e257600080fd5b806345755dd61461044b57806347350e9f1461045e5780634eac42351461048657600080fd5b8063227000371161032557806339ba9f86116102ff57806339ba9f861461041757806339d65834146104285780633b99bcee146104305780634003f34d1461044357600080fd5b806322700037146103f4578063267f4ac3146103fc5780632ead10981461040f57600080fd5b80630fe3d9b7116103615780630fe3d9b7146103c9578063144ee4b5146103d15780631cc1cf46146103d95780631f3f19ab146103e157600080fd5b806301daa38f146103885780630895326f146103925780630c340a24146103a9575b600080fd5b6103906106de565b005b6013545b6040519081526020015b60405180910390f35b6103b161081d565b6040516001600160a01b0390911681526020016103a0565b61039061089c565b6103906109d4565b600754610396565b6103906103ef366004614266565b610aec565b601a54610396565b61039061040a366004614266565b610cee565b600b54610396565b6005546001600160a01b03166103b1565b600954610396565b61039061043e366004614433565b610d8a565b601254610396565b6103966104593660046143dc565b610fa0565b61047161046c366004614266565b61110a565b604080519283526020830191909152016103a0565b6103966104943660046143dc565b6112fb565b6103966104a73660046143dc565b611343565b6104bf6104ba3660046143dc565b6114a4565b604080519384526020840192909252908201526060016103a0565b6103b1611ae4565b6003546001600160a01b03166103b1565b610396610501366004614266565b611aee565b6002546001600160a01b03166103b1565b61039661052536600461432e565b611bc2565b6103966105383660046142a0565b6120d6565b600c54610396565b600a54610396565b61039661220d565b600854610396565b6000546001600160a01b03166103b1565b61039661057c36600461432e565b612249565b600d54610396565b6104bf6123e6565b61039661059f3660046143dc565b6124e3565b600654610396565b601a5460405190151581526020016103a0565b601654610396565b6004546001600160a01b03166103b1565b6103966105e636600461432e565b612506565b600e54610396565b6104bf612699565b600f54610396565b601454610396565b601554610396565b6001546001600160a01b03166103b1565b6103b1612715565b61039061063a3660046142d9565b612757565b6103b16127fc565b61039661065536600461440e565b612806565b6104bf6106683660046143dc565b612a48565b6019546001600160a01b03166103b1565b61068661306b565b6040516103a093929190614659565b6103906106a336600461440e565b6130aa565b61039061329b565b6103906106be366004614266565b61333f565b601154610396565b6103966106d9366004614266565b6133cb565b6106e6612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b15801561071e57600080fd5b505afa158015610732573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061075691906143ba565b1561077c5760405162461bcd60e51b81526004016107739061462e565b60405180910390fd5b6002546001600160a01b031633146107d65760405162461bcd60e51b815260206004820152601a60248201527f4d4c3a41423a4e4f545f50454e44494e475f424f52524f5745520000000000006044820152606401610773565b600280546001600160a01b031990811690915560008054339216821781556040517f29bac0ac2b15405bfcc160bb74b6ae7a559b7674ce33db80785ada73e38204d29190a2565b6000610827612715565b6001600160a01b0316630c340a246040518163ffffffff1660e01b815260040160206040518083038186803b15801561085f57600080fd5b505afa158015610873573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108979190614283565b905090565b6108a4612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b1580156108dc57600080fd5b505afa1580156108f0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091491906143ba565b156109315760405162461bcd60e51b81526004016107739061462e565b6003546001600160a01b0316331461098b5760405162461bcd60e51b815260206004820152601860248201527f4d4c3a414c3a4e4f545f50454e44494e475f4c454e44455200000000000000006044820152606401610773565b600380546001600160a01b031990811690915560018054339216821790556040517fd6165838d2e3db87aa1002b548048673fc6427eefbd1b914e100f3a0deae23e390600090a2565b601a546001546001600160a01b03163314610a255760405162461bcd60e51b815260206004820152601160248201527026a61d2926249d2727aa2fa622a72222a960791b6044820152606401610773565b80610a685760405162461bcd60e51b815260206004820152601360248201527213530e9493124e9393d517d253541052549151606a1b6044820152606401610773565b80421115610aab5760405162461bcd60e51b815260206004820152601060248201526f4d4c3a524c493a504153545f4441544560801b6044820152606401610773565b60128190556000601a556040518181527f962d5a38dc48af765ecb4f177a88713b592b5bf59e64f497ab33af13b7c0e9de906020015b60405180910390a150565b610af4612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b158015610b2c57600080fd5b505afa158015610b40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6491906143ba565b15610b815760405162461bcd60e51b81526004016107739061462e565b6000546001600160a01b03163314610bd15760405162461bcd60e51b815260206004820152601360248201527226a61d29a8211d2727aa2fa127a92927aba2a960691b6044820152606401610773565b610bd9612715565b60405163eaf6e48360e01b81526001600160a01b038381166004830152919091169063eaf6e4839060240160206040518083038186803b158015610c1c57600080fd5b505afa158015610c30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5491906143ba565b610ca05760405162461bcd60e51b815260206004820152601760248201527f4d4c3a5350423a494e56414c49445f424f52524f5745520000000000000000006044820152606401610773565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527f10f06072822ef73860fedb88933f968d20bb4aadce8a8d360d1124cb6ce1e0b290602001610ae1565b6001546001600160a01b03163314610d3c5760405162461bcd60e51b815260206004820152601160248201527026a61d29a8261d2727aa2fa622a72222a960791b6044820152606401610773565b600380546001600160a01b0319166001600160a01b0383169081179091556040519081527fa3ab02442c80a4102475683f16513c9139a89142be9db9804edfcfbb379fc49290602001610ae1565b610d92612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b158015610dca57600080fd5b505afa158015610dde573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e0291906143ba565b15610e1f5760405162461bcd60e51b81526004016107739061462e565b610e27612715565b6001600160a01b031663be7c13f76040518163ffffffff1660e01b815260040160206040518083038186803b158015610e5f57600080fd5b505afa158015610e73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e979190614283565b6001600160a01b0316336001600160a01b031614610ef75760405162461bcd60e51b815260206004820152601760248201527f4d4c3a553a4e4f545f53454355524954595f41444d494e0000000000000000006044820152606401610773565b7faaaa7ee6b0c2f4ee1fa7312c7d5b3623a434da5a1a9ce3cb6e629caa23454ab6838383604051610f2a939291906146ba565b60405180910390a1610f3a6138ac565b6001600160a01b031663fe69f7088484846040518463ffffffff1660e01b8152600401610f69939291906146ba565b600060405180830381600087803b158015610f8357600080fd5b505af1158015610f97573d6000803e3d6000fd5b50505050505050565b6000610faa612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b158015610fe257600080fd5b505afa158015610ff6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061101a91906143ba565b156110375760405162461bcd60e51b81526004016107739061462e565b8115806110575750600554611057906001600160a01b03163330856138db565b6110a35760405162461bcd60e51b815260206004820152601a60248201527f4d4c3a52463a5452414e534645525f46524f4d5f4641494c45440000000000006044820152606401610773565b6005546110b8906001600160a01b0316611aee565b905080600f60008282546110cc919061471b565b90915550506040518181527f278e51d3323fbf18b9fb8df3f8b97e31b145bc1146c52e764cf4aa1bfc4ba17d906020015b60405180910390a1919050565b60015460009081906001600160a01b0316331461115b5760405162461bcd60e51b815260206004820152600f60248201526e26a61d291d2727aa2fa622a72222a960891b6044820152606401610773565b60125480158015906111785750600654611175908261471b565b42115b6111ba5760405162461bcd60e51b815260206004820152601360248201527213530e948e9393d517d25397d1115190555315606a1b6044820152606401610773565b6111c2613952565b60006011819055600f8190556004546001600160a01b0316906111e482611aee565b94508414806111f957506111f981868661398b565b61123e5760405162461bcd60e51b815260206004820152601660248201527513530e948e90d7d514905394d1915497d1905253115160521b6044820152606401610773565b6005546001600160a01b0316600061125582611aee565b945084148061126a575061126a81878661398b565b6112af5760405162461bcd60e51b815260206004820152601660248201527513530e948e9197d514905394d1915497d1905253115160521b6044820152606401610773565b60408051868152602081018690526001600160a01b038816917f027e623aab0b174da270ff529cad1c54f09182651e07437d2ac557929b9e5b49910160405180910390a2505050915091565b60008061131d60145484600f546113129190614774565b600d54600c546139c8565b60115490915080821161133157600061133b565b61133b8183614774565b949350505050565b600061134d612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b15801561138557600080fd5b505afa158015611399573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113bd91906143ba565b156113da5760405162461bcd60e51b81526004016107739061462e565b8115806113fa57506004546113fa906001600160a01b03163330856138db565b6114465760405162461bcd60e51b815260206004820152601a60248201527f4d4c3a50433a5452414e534645525f46524f4d5f4641494c45440000000000006044820152606401610773565b60045461145b906001600160a01b0316611aee565b9050806011600082825461146f919061471b565b90915550506040518181527f437d44b2c697fb69e2b2f25f57fd844e376c25ed28ed5a9c4be88aa1e5c87d12906020016110fd565b60008054819081906001600160a01b03163314156117a7576114c4612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b1580156114fc57600080fd5b505afa158015611510573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153491906143ba565b156115515760405162461bcd60e51b81526004016107739061462e565b8315806115715750600554611571906001600160a01b03163330876138db565b6115bd5760405162461bcd60e51b815260206004820152601a60248201527f4d4c3a4d503a5452414e534645525f46524f4d5f4641494c45440000000000006044820152606401610773565b6115c5613a18565b6115cd612699565b506000601681905591945092506115e4838561471b565b60055490915081906115fe906001600160a01b0316611aee565b600f5461160b919061471b565b6116159190614774565b600f556116226001613a28565b60135460125491935090600060018314156116445761163f613952565b611681565b600754611651908361471b565b905080601281905550866014600082825461166c9190614774565b9091555061167d9050600184614774565b6013555b60408051888152602081018890529081018690527fcf358e925a8e033c6db877f18d10df6f21cd04ef165537bad5fc814eb23af9609060600160405180910390a16005546001546116df916001600160a01b0390811691168661398b565b6116fb5760405162461bcd60e51b8152600401610773906145ff565b60015460405163b5add71760e01b8152600481018990526024810188905260448101849052606481018390526001600160a01b039091169063b5add71790608401600060405180830381600087803b15801561175657600080fd5b505af115801561176a573d6000803e3d6000fd5b50506001546040518781526001600160a01b0390911692506000805160206147cd833981519152915060200160405180910390a250505050611add565b600f546117b2612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b1580156117ea57600080fd5b505afa1580156117fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061182291906143ba565b1561183f5760405162461bcd60e51b81526004016107739061462e565b84158061185f575060055461185f906001600160a01b03163330886138db565b6118ab5760405162461bcd60e51b815260206004820152601a60248201527f4d4c3a4d503a5452414e534645525f46524f4d5f4641494c45440000000000006044820152606401610773565b6118b3613a18565b6118bb612699565b506000601681905591955093506118d2848661471b565b60055490915081906118ec906001600160a01b0316611aee565b600f546118f9919061471b565b6119039190614774565b600f556119106001613a28565b60135460125491945090600060018314156119325761192d613952565b61196f565b60075461193f908361471b565b905080601281905550876014600082825461195a9190614774565b9091555061196b9050600184614774565b6013555b60408051898152602081018990529081018790527fcf358e925a8e033c6db877f18d10df6f21cd04ef165537bad5fc814eb23af9609060600160405180910390a16005546001546119cd916001600160a01b0390811691168661398b565b6119e95760405162461bcd60e51b8152600401610773906145ff565b60015460405163b5add71760e01b8152600481018a90526024810189905260448101849052606481018390526001600160a01b039091169063b5add71790608401600060405180830381600087803b158015611a4457600080fd5b505af1158015611a58573d6000803e3d6000fd5b50506001546040518781526001600160a01b0390911692506000805160206147cd833981519152915060200160405180910390a25050505080600f541015611adb5760405162461bcd60e51b81526020600482015260166024820152754d4c3a43414e4e4f545f5553455f4452415741424c4560501b6044820152606401610773565b505b9193909250565b6000610897613c0a565b6005546000906001600160a01b03838116911614611b0d576000611b11565b600f545b6004546001600160a01b03848116911614611b2d576000611b31565b6011545b6040516370a0823160e01b81523060048201526001600160a01b038516906370a082319060240160206040518083038186803b158015611b7057600080fd5b505afa158015611b84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba891906143f5565b611bb29190614774565b611bbc9190614774565b92915050565b6001546000906001600160a01b03163314611c135760405162461bcd60e51b815260206004820152601160248201527026a61d20a72a1d2727aa2fa622a72222a960791b6044820152606401610773565b611c1f85858585613c34565b90508060155414611c725760405162461bcd60e51b815260206004820152601a60248201527f4d4c3a414e543a434f4d4d49544d454e545f4d49534d415443480000000000006044820152606401610773565b6001600160a01b0385163b611cc95760405162461bcd60e51b815260206004820152601960248201527f4d4c3a414e543a494e56414c49445f524546494e414e434552000000000000006044820152606401610773565b83421115611d195760405162461bcd60e51b815260206004820152601960248201527f4d4c3a414e543a455850495245445f434f4d4d49544d454e54000000000000006044820152606401610773565b600754601254600d54600082611d2f854261471b565b10611d4d57611d3e8484614774565b611d489042614774565b611d50565b60005b6019546040516341a703bb60e01b815260048101859052602481018390529192506001600160a01b03169081906341a703bb90604401600060405180830381600087803b158015611da057600080fd5b505af1158015611db4573d6000803e3d6000fd5b505050506000611dc3426124e3565b90508060166000828254611dd7919061471b565b9091555050600060158190555b88811015611eb45760008c6001600160a01b03168b8b84818110611e0a57611e0a6147a1565b9050602002810190611e1c91906146d4565b604051611e2a929190614553565b600060405180830381855af49150503d8060008114611e65576040519150601f19603f3d011682016040523d82523d6000602084013e611e6a565b606091505b5050905080611eab5760405162461bcd60e51b815260206004820152600d60248201526c13530e9053950e919052531151609a1b6044820152606401610773565b50600101611de4565b507f7150c332bd889236b6ab42cc34f0853631ceb58827f58a8697b682f13e390a8c878c8c8c8c604051611eec9594939291906145c6565b60405180910390a1600554600d5460075497506001600160a01b0390911690611f15884261471b565b601255611f20613a18565b6040516377cf0ddb60e11b815260048101829052602481018990526001600160a01b0385169063ef9e1bb690604401600060405180830381600087803b158015611f6957600080fd5b505af1158015611f7d573d6000803e3d6000fd5b50506040516327d180b560e01b81526001600160a01b03858116600483015260248201859052871692506327d180b59150604401602060405180830381600087803b158015611fcb57600080fd5b505af1158015611fdf573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061200391906143f5565b600f60008282546120149190614774565b909155506120229050613c6d565b61206e5760405162461bcd60e51b815260206004820152601e60248201527f4d4c3a414e543a494e53554646494349454e545f434f4c4c41544552414c00006044820152606401610773565b600061207983611aee565b146120c65760405162461bcd60e51b815260206004820152601760248201527f4d4c3a414e543a554e45585045435445445f46554e44530000000000000000006044820152606401610773565b5050505050505050949350505050565b60006120e0612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b15801561211857600080fd5b505afa15801561212c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061215091906143ba565b1561216d5760405162461bcd60e51b81526004016107739061462e565b816001600160a01b0316836001600160a01b03167ff1f6a55e7ad487ac8dd8e1d4517348d3b410a7a0bc405ef87b09078dc51b23b66121ab86611aee565b60405181815290945060200160405180910390a36121ca83838361398b565b611bbc5760405162461bcd60e51b815260206004820152601460248201527313530e94ce9514905394d1915497d1905253115160621b6044820152606401610773565b600080612224601454600f54600d54600c546139c8565b601154909150818111612238576000612242565b6122428282614774565b9250505090565b6000612253612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b15801561228b57600080fd5b505afa15801561229f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122c391906143ba565b156122e05760405162461bcd60e51b81526004016107739061462e565b6000546001600160a01b031633146123305760405162461bcd60e51b815260206004820152601360248201527226a61d28272a1d2727aa2fa127a92927aba2a960691b6044820152606401610773565b428410156123805760405162461bcd60e51b815260206004820152601760248201527f4d4c3a504e543a494e56414c49445f444541444c494e450000000000000000006044820152606401610773565b7ff94d2f0322894aaf1bce14561461a8b8b6c9b11a77bbe80f20b804da8a95e4b7826123ad5760006123b9565b6123b986868686613c34565b6015819055915081868686866040516123d69594939291906145c6565b60405180910390a1949350505050565b60195460135460405163e0b58e0d60e01b815230600482015260248101919091526000918291829182918291829182916001600160a01b03169063e0b58e0d9060440160806040518083038186803b15801561244157600080fd5b505afa158015612455573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124799190614466565b93509350935093508083838661248f919061471b565b612499919061471b565b6124a3919061471b565b9450601654670de0b6b3a76400006009546014549950896124c49190614755565b6124ce9190614733565b6124d8919061471b565b955050505050909192565b6000611bbc82600754601454600e54600854601354601254600a54600b54613c8d565b6000612510612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b15801561254857600080fd5b505afa15801561255c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061258091906143ba565b1561259d5760405162461bcd60e51b81526004016107739061462e565b6000546001600160a01b03163314806125c057506001546001600160a01b031633145b6125fd5760405162461bcd60e51b815260206004820152600e60248201526d09a9874a49ca8749c9ebe82aaa8960931b6044820152606401610773565b61260985858585613c34565b9050806015541461265c5760405162461bcd60e51b815260206004820152601a60248201527f4d4c3a524e543a434f4d4d49544d454e545f4d49534d415443480000000000006044820152606401610773565b60006015556040517f47244a449377da5fd10e98d86d118dee442e842fc34f05179c973cfcff6acba7906123d690839088908890889088906145c6565b60008060006126a66141e1565b6126ae6141ff565b6126cf42601254600754601454600e54601354600854600a54600b54613cfa565b604082015160208301518351949950929550909350916126ef919061471b565b6126f9919061471b565b6020820151825191955061270c9161471b565b92505050909192565b600061271f6138ac565b6001600160a01b0316633a60339a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561085f57600080fd5b61275f6138ac565b6001600160a01b0316336001600160a01b0316146127b25760405162461bcd60e51b815260206004820152601060248201526f4d4c3a4d3a4e4f545f464143544f525960801b6044820152606401610773565b6127bd838383613e17565b6127f75760405162461bcd60e51b815260206004820152600b60248201526a13530e934e91905253115160aa1b6044820152606401610773565b505050565b60006108976138ac565b6000612810612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b15801561284857600080fd5b505afa15801561285c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061288091906143ba565b1561289d5760405162461bcd60e51b81526004016107739061462e565b6000546001600160a01b031633146128ec5760405162461bcd60e51b815260206004820152601260248201527126a61d22231d2727aa2fa127a92927aba2a960711b6044820152606401610773565b816001600160a01b03167f7578fe8c4d9f6fc38fdad20d219b0ce47d38bbf8a72bdb26867809f24119363d8460405161292791815260200190565b60405180910390a2600061293a846112fb565b9050801561297b5760045460009061295a906001600160a01b0316611aee565b905061297781831161296d576000611343565b6104a78284614774565b9250505b83600f600082825461298d9190614774565b90915550506005546129a9906001600160a01b0316848661398b565b6129ed5760405162461bcd60e51b815260206004820152601560248201527413530e91118e9514905394d1915497d19052531151605a1b6044820152606401610773565b6129f5613c6d565b612a415760405162461bcd60e51b815260206004820152601d60248201527f4d4c3a44463a494e53554646494349454e545f434f4c4c41544552414c0000006044820152606401610773565b5092915050565b60008054819081906001600160a01b0316331415612d4157612a68612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b158015612aa057600080fd5b505afa158015612ab4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad891906143ba565b15612af55760405162461bcd60e51b81526004016107739061462e565b831580612b155750600554612b15906001600160a01b03163330876138db565b612b615760405162461bcd60e51b815260206004820152601a60248201527f4d4c3a434c3a5452414e534645525f46524f4d5f4641494c45440000000000006044820152606401610773565b60125442811015612bac5760405162461bcd60e51b81526020600482015260156024820152744d4c3a434c3a5041594d454e545f49535f4c41544560581b6044820152606401610773565b612bb4613a18565b612bbc6123e6565b50600060168190559195509350612bd3848661471b565b6005549091508190612bed906001600160a01b0316611aee565b600f54612bfa919061471b565b612c049190614774565b600f55601354612c1390613a28565b9250612c1d613952565b60408051868152602081018690529081018490527f4acb957de3799dd3d95bb7da6bcfbca6f5a33812d69ad37816ed87e79b6327d69060600160405180910390a1600554600154612c7b916001600160a01b0390811691168361398b565b612c975760405162461bcd60e51b8152600401610773906145ff565b60015460405163b5add71760e01b8152600481018790526024810186905260448101849052600060648201526001600160a01b039091169063b5add71790608401600060405180830381600087803b158015612cf257600080fd5b505af1158015612d06573d6000803e3d6000fd5b50506001546040518481526001600160a01b0390911692506000805160206147cd833981519152915060200160405180910390a25050611add565b600f54612d4c612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b158015612d8457600080fd5b505afa158015612d98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dbc91906143ba565b15612dd95760405162461bcd60e51b81526004016107739061462e565b841580612df95750600554612df9906001600160a01b03163330886138db565b612e455760405162461bcd60e51b815260206004820152601a60248201527f4d4c3a434c3a5452414e534645525f46524f4d5f4641494c45440000000000006044820152606401610773565b60125442811015612e905760405162461bcd60e51b81526020600482015260156024820152744d4c3a434c3a5041594d454e545f49535f4c41544560581b6044820152606401610773565b612e98613a18565b612ea06123e6565b50600060168190559196509450612eb7858761471b565b6005549091508190612ed1906001600160a01b0316611aee565b600f54612ede919061471b565b612ee89190614774565b600f55601354612ef790613a28565b9350612f01613952565b60408051878152602081018790529081018590527f4acb957de3799dd3d95bb7da6bcfbca6f5a33812d69ad37816ed87e79b6327d69060600160405180910390a1600554600154612f5f916001600160a01b0390811691168361398b565b612f7b5760405162461bcd60e51b8152600401610773906145ff565b60015460405163b5add71760e01b8152600481018890526024810187905260448101849052600060648201526001600160a01b039091169063b5add71790608401600060405180830381600087803b158015612fd657600080fd5b505af1158015612fea573d6000803e3d6000fd5b50506001546040518481526001600160a01b0390911692506000805160206147cd833981519152915060200160405180910390a2505080600f541015611adb5760405162461bcd60e51b81526020600482015260166024820152754d4c3a43414e4e4f545f5553455f4452415741424c4560501b6044820152606401610773565b60006130756141e1565b61307d6141ff565b61309e42601254600754601454600e54601354600854600a54600b54613cfa565b91959094509092509050565b6130b2612715565b6001600160a01b031663425fad586040518163ffffffff1660e01b815260040160206040518083038186803b1580156130ea57600080fd5b505afa1580156130fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061312291906143ba565b1561313f5760405162461bcd60e51b81526004016107739061462e565b6000546001600160a01b0316331461318e5760405162461bcd60e51b815260206004820152601260248201527126a61d29219d2727aa2fa127a92927aba2a960711b6044820152606401610773565b806001600160a01b03167f97b446ee2df422b7273fe6d658674835f9de3319d131c229f9a2f8ed62a76193836040516131c991815260200190565b60405180910390a281601160008282546131e39190614774565b90915550506004546131ff906001600160a01b0316828461398b565b6132435760405162461bcd60e51b815260206004820152601560248201527413530e9490ce9514905394d1915497d19052531151605a1b6044820152606401610773565b61324b613c6d565b6132975760405162461bcd60e51b815260206004820152601d60248201527f4d4c3a52433a494e53554646494349454e545f434f4c4c41544552414c0000006044820152606401610773565b5050565b6012546001546001600160a01b031633146132eb5760405162461bcd60e51b815260206004820152601060248201526f26a61d24a61d2727aa2fa622a72222a960811b6044820152606401610773565b60008142116132fa57426132fc565b815b90507f54c4bb2a061eac3afc1daf65bd7a75a0cdb4ac02824757f40019dff2da5849358160405161332f91815260200190565b60405180910390a1601255601a55565b6133476138ac565b6001600160a01b0316336001600160a01b03161461339b5760405162461bcd60e51b81526020600482015260116024820152704d4c3a53493a4e4f545f464143544f525960781b6044820152606401610773565b6001600160a01b03167f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b50565b600180546001600160a01b0319166001600160a01b03831690811790915560009061342f5760405162461bcd60e51b815260206004820152601460248201527326a61d23261d24a72b20a624a22fa622a72222a960611b6044820152606401610773565b6000826001600160a01b031663c45a01556040518163ffffffff1660e01b815260040160206040518083038186803b15801561346a57600080fd5b505afa15801561347e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134a29190614283565b90506134ac612715565b604051636167f93160e01b81526b2627a0a72fa6a0a720a3a2a960a11b60048201526001600160a01b0383811660248301529190911690636167f9319060440160206040518083038186803b15801561350457600080fd5b505afa158015613518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353c91906143ba565b6135805760405162461bcd60e51b81526020600482015260156024820152744d4c3a464c3a494e56414c49445f464143544f525960581b6044820152606401610773565b6040516335a2735f60e11b81526001600160a01b038481166004830152821690636b44e6be9060240160206040518083038186803b1580156135c157600080fd5b505afa1580156135d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135f991906143ba565b61363e5760405162461bcd60e51b81526020600482015260166024820152754d4c3a464c3a494e56414c49445f494e5354414e434560501b6044820152606401610773565b60125415801561364f575060135415155b61368f5760405162461bcd60e51b81526020600482015260116024820152704d4c3a464c3a4c4f414e5f41435449564560781b6044820152606401610773565b600554600754600d546019546001600160a01b03938416936136b691859116600019613e90565b6136f75760405162461bcd60e51b815260206004820152601260248201527113530e91930e9054141493d59157d190525360721b6044820152606401610773565b6019546040516377cf0ddb60e11b815260048101839052602481018490526001600160a01b039091169063ef9e1bb690604401600060405180830381600087803b15801561374457600080fd5b505af1158015613758573d6000803e3d6000fd5b50506019546040516327d180b560e01b81526001600160a01b038781166004830152602482018690526000945090911691506327d180b590604401602060405180830381600087803b1580156137ad57600080fd5b505af11580156137c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137e591906143f5565b90506137f18183614774565b600f5560006137ff85611aee565b146138455760405162461bcd60e51b81526020600482015260166024820152754d4c3a464c3a554e45585045435445445f46554e445360501b6044820152606401610773565b866001600160a01b03167fcd909ec339185c4598a4096e174308fbdf136d117f230960f873a2f2e81f63af8360148190559750878542613885919061471b565b60128190556040805192835260208301919091520160405180910390a25050505050919050565b60006138d67f7a45a402e4cb6e08ebc196f20f66d5d30e67285a2a8aa80503fa409e727a4af15490565b919050565b6040516001600160a01b03808516602483015283166044820152606481018290526000906139499086906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613f0c565b95945050505050565b60006006819055600781905560088190556009819055600a819055600b819055600e819055601281905560138190556014819055601a55565b6040516001600160a01b0383166024820152604481018290526000906139be90859063a9059cbb60e01b90606401613912565b90505b9392505050565b600083851115613a0d57826001816139e08789614774565b6139ea9086614755565b6139f4919061471b565b6139fe9190614774565b613a089190614733565b613949565b506000949350505050565b601a54613a2157565b6000601a55565b6005546040516370a0823160e01b815230600482015260009182916001600160a01b03909116906370a082319060240160206040518083038186803b158015613a7057600080fd5b505afa158015613a84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613aa891906143f5565b6019546005546040516376bd6e5160e01b81526001600160a01b0391821660048201526024810187905292935016906376bd6e5190604401602060405180830381600087803b158015613afa57600080fd5b505af1158015613b0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b3291906143f5565b506005546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b158015613b7757600080fd5b505afa158015613b8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613baf91906143f5565b905080821115613be257613bc38183614774565b925082600f6000828254613bd79190614774565b90915550613c039050565b613bec8282614774565b600f6000828254613bfd919061471b565b90915550505b5050919050565b60006138d67f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b600084848484604051602001613c4d949392919061459e565b604051602081830303815290604052805190602001209050949350505050565b6000613c83601454600f54600d54600c546139c8565b6011541015905090565b600083613c9a8a8c61471b565b1015613ca857506000613ced565b6000613cb48a86614774565b613cbe908c614774565b9050613ccd898989848a613fac565b9250613cdf90508b8a8988888861409f565b613ce9908361471b565b9150505b9998505050505050505050565b6000613d046141e1565b613d0c6141ff565b613d198989888d8b613fac565b8352925060018714613d2b5782613d2d565b885b9250613d3d8c8a888e898961409f565b8260016020020152601654826002602002015260195460405163e0b58e0d60e01b8152306004820152600160248201526000918291829182916001600160a01b039091169063e0b58e0d9060440160806040518083038186803b158015613da357600080fd5b505afa158015613db7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ddb9190614466565b93509350935093508284613def919061471b565b8552613dfb818361471b565b602086015250949e939d50919b50919950505050505050505050565b6000833b80613e2a5760009150506139c1565b846001600160a01b03168484604051613e44929190614553565b600060405180830381855af49150503d8060008114613e7f576040519150601f19603f3d011682016040523d82523d6000602084013e613e84565b606091505b50909695505050505050565b6040516001600160a01b038316602482015260006044820181905290613ec390859063095ea7b360e01b90606401613912565b613ecf575060006139c1565b81613edc575060016139c1565b6040516001600160a01b0384166024820152604481018390526139be90859063095ea7b360e01b90606401613912565b60006001600160a01b0383163b613f2557506000611bbc565b6060836001600160a01b031683604051613f3f9190614563565b6000604051808303816000865af19150503d8060008114613f7c576040519150601f19603f3d011682016040523d82523d6000602084013e613f81565b606091505b50909250905081801561133b57508051158061133b57508080602001905181019061133b91906143ba565b6000806000613fbb868661413b565b90506000613fe3613fd483670de0b6b3a764000061471b565b86670de0b6b3a7640000614156565b9050670de0b6b3a764000081116140165784613fff898b614774565b6140099190614733565b6000935093505050614095565b600061402a670de0b6b3a764000083614774565b838a670de0b6b3a764000061403f868f614755565b6140499190614733565b6140539190614774565b61405d9190614755565b6140679190614733565b90506140748a89896141b8565b93508381101561408557600061408f565b61408f8482614774565b94505050505b9550959350505050565b60008387116140b057506000614131565b6000620151806140c0868a614774565b6140cd906201517f61471b565b6140d79190614733565b6140e49062015180614755565b90506140fa876140f4858961471b565b836141b8565b614104908361471b565b9150670de0b6b3a76400006141198886614755565b6141239190614733565b61412d908361471b565b9150505b9695505050505050565b60006301e1338061414c8385614755565b6139c19190614733565b6000600183166141665781614168565b835b90505b60019290921c9182156139c157816141838580614755565b61418d9190614733565b93506001831661419c5761416b565b816141a78583614755565b6141b19190614733565b905061416b565b6000670de0b6b3a76400006141cd848461413b565b6141d79086614755565b6139be9190614733565b60405180606001604052806003906020820280368337509192915050565b60405180604001604052806002906020820280368337509192915050565b60008083601f84011261422f57600080fd5b50813567ffffffffffffffff81111561424757600080fd5b60208301915083602082850101111561425f57600080fd5b9250929050565b60006020828403121561427857600080fd5b81356139c1816147b7565b60006020828403121561429557600080fd5b81516139c1816147b7565b600080604083850312156142b357600080fd5b82356142be816147b7565b915060208301356142ce816147b7565b809150509250929050565b6000806000604084860312156142ee57600080fd5b83356142f9816147b7565b9250602084013567ffffffffffffffff81111561431557600080fd5b6143218682870161421d565b9497909650939450505050565b6000806000806060858703121561434457600080fd5b843561434f816147b7565b935060208501359250604085013567ffffffffffffffff8082111561437357600080fd5b818701915087601f83011261438757600080fd5b81358181111561439657600080fd5b8860208260051b85010111156143ab57600080fd5b95989497505060200194505050565b6000602082840312156143cc57600080fd5b815180151581146139c157600080fd5b6000602082840312156143ee57600080fd5b5035919050565b60006020828403121561440757600080fd5b5051919050565b6000806040838503121561442157600080fd5b8235915060208301356142ce816147b7565b60008060006040848603121561444857600080fd5b83359250602084013567ffffffffffffffff81111561431557600080fd5b6000806000806080858703121561447c57600080fd5b505082516020840151604085015160609095015191969095509092509050565b818352600060208085019450848460051b86018460005b8781101561451d5783830389528135601e198836030181126144d457600080fd5b8701803567ffffffffffffffff8111156144ed57600080fd5b8036038913156144fc57600080fd5b614509858289850161452a565b9a87019a94505050908401906001016144b3565b5090979650505050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8183823760009101908152919050565b6000825160005b81811015614584576020818601810151858301520161456a565b81811115614593576000828501525b509190910192915050565b60018060a01b038516815283602082015260606040820152600061413160608301848661449c565b85815260018060a01b03851660208201528360408201526080606082015260006145f460808301848661449c565b979650505050505050565b60208082526015908201527413530e93540e9514905394d1915497d19052531151605a1b604082015260600190565b602080825260119082015270130e941493d513d0d3d317d4105554d151607a1b604082015260600190565b83815260c0810160208083018560005b600381101561468657815183529183019190830190600101614669565b505050608083018460005b60028110156146ae57815183529183019190830190600101614691565b50505050949350505050565b83815260406020820152600061394960408301848661452a565b6000808335601e198436030181126146eb57600080fd5b83018035915067ffffffffffffffff82111561470657600080fd5b60200191503681900382131561425f57600080fd5b6000821982111561472e5761472e61478b565b500190565b60008261475057634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561476f5761476f61478b565b500290565b6000828210156147865761478661478b565b500390565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6001600160a01b03811681146133c857600080fdfe6bd56533ce1c8ea03f7b858ac441b5a86d140a793a7c9e3faecbbe517c2c8791a26469706673582212204a309c37cbae06ae4046df36b05aa1ac996ec534c14d5709848916960b7ff5da64736f6c63430008070033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
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.