Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions packages/contracts/.openzeppelin/unknown-8453.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@
"address": "0x48EA70BCe76FE2F0c79B29Bf852a1DCF957982aa",
"txHash": "0x99bcdd5255ef14b7f295a8517d4e5072f15c8eb8059613fe2990c073902cf638",
"kind": "transparent"
},
{
"address": "0xA59e62116a3bcECb2ECe385558533dCcE1aCad50",
"txHash": "0x128c45cdf0585c1d63fd3e504305ac84ce57c8a3a2f03edf848f400d3fa58a5f",
"kind": "transparent"
}
],
"impls": {
Expand Down Expand Up @@ -7918,6 +7923,65 @@
"types": {},
"namespaces": {}
}
},
"825729ccfef1b6f4baea3aaa49460a9097dc3cf4111678638774317123df4bcd": {
"address": "0x2E917438FDb3969c5eBF63Df71712D10c9EcD89d",
"txHash": "0x1fcf5d26c1471a8c162eac2f6e4b82dac79a9756b10affc2435cc73c5ce0bef1",
"layout": {
"solcVersion": "0.8.11",
"storage": [
{
"label": "_initialized",
"offset": 0,
"slot": "0",
"type": "t_uint8",
"contract": "Initializable",
"src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62",
"retypedFrom": "bool"
},
{
"label": "_initializing",
"offset": 1,
"slot": "0",
"type": "t_bool",
"contract": "Initializable",
"src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67"
},
{
"label": "TELLER_V2",
"offset": 2,
"slot": "0",
"type": "t_contract(ITellerV2)6996",
"contract": "MultiSourceBorrow",
"src": "contracts/LenderCommitmentForwarder/MultiSourceBorrow.sol:31"
}
],
"types": {
"t_bool": {
"label": "bool",
"numberOfBytes": "1"
},
"t_contract(ITellerV2)6996": {
"label": "contract ITellerV2",
"numberOfBytes": "20"
},
"t_uint8": {
"label": "uint8",
"numberOfBytes": "1"
}
},
"namespaces": {}
}
},
"0fecd24252781a3a9a08df928585d681c8811f5c35004a980a5debeb015f5f3c": {
"address": "0xb02165859CE5F61597BC09C8c0F78276777D9bf0",
"txHash": "0x570e3700f92084d0a87a7d8740717813942931ff2b5d17052c599739490772b5",
"layout": {
"solcVersion": "0.8.11",
"storage": [],
"types": {},
"namespaces": {}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// Contracts
import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

// Interfaces
import "../interfaces/ITellerV2.sol";
import "../interfaces/IProtocolFee.sol";
import "../interfaces/ITellerV2Storage.sol";
import "../interfaces/IMarketRegistry.sol";
import "../interfaces/ISmartCommitment.sol";
import "../interfaces/ISmartCommitmentForwarder.sol";
import "../interfaces/IFlashRolloverLoan_G4.sol";
import "../libraries/NumbersLib.sol";

import { ILenderCommitmentForwarder } from "../interfaces/ILenderCommitmentForwarder.sol";

import { ILenderCommitmentForwarder_U1 } from "../interfaces/ILenderCommitmentForwarder_U1.sol";

import '../libraries/uniswap/periphery/libraries/TransferHelper.sol';


contract MultiSourceBorrow
{
using AddressUpgradeable for address;
using NumbersLib for uint256;

/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
ITellerV2 public immutable TELLER_V2;
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable



struct AcceptCommitmentArgs {
uint256 commitmentId;
address smartCommitmentAddress; //if this is not address(0), we will use this ! leave empty if not used.
uint256 principalAmount;
uint256 collateralAmount;
uint256 collateralTokenId;
address collateralTokenAddress;
uint16 interestRate;
uint32 loanDuration;
bytes32[] merkleProof; //empty array if not used
}


constructor(
address _tellerV2
) {
TELLER_V2 = ITellerV2(_tellerV2);
}



/*

*/
function acceptCommitmentWithMultiSource(
address _commitmentForwarder,
AcceptCommitmentArgs calldata _acceptCommitmentArgs,
address poolAddress, //works with teller PoolV2
uint256 poolWithdrawAmount,
address stakingContractAddress,
uint256 stakingWithdrawAmount,
address recipient

) external returns (uint256 bidId_) {


address principalTokenAddress = address(0);
uint256 balanceBefore;

// Get principal token address first
if (_acceptCommitmentArgs.smartCommitmentAddress != address(0)) {
principalTokenAddress = ISmartCommitment(_acceptCommitmentArgs.smartCommitmentAddress).getPrincipalTokenAddress();
} else {
principalTokenAddress = ILenderCommitmentForwarder_U1(_commitmentForwarder)
.getCommitmentPrincipalTokenAddress(_acceptCommitmentArgs.commitmentId);
}




// The collateral all needs to go in to the borrowers wallet
// Transfer collateral from borrower into this contract
if (_acceptCommitmentArgs.collateralAmount > 0) {
TransferHelper.safeTransferFrom(
_acceptCommitmentArgs.collateralTokenAddress,
msg.sender,
address(this),
_acceptCommitmentArgs.collateralAmount
);
}

// Withdraw from pool if specified (need to be approved)
if (poolAddress != address(0) && poolWithdrawAmount > 0) {
(bool success, ) = poolAddress.call(
abi.encodeWithSignature(
"withdraw(uint256,address,address)",
poolWithdrawAmount,
address(this), // receiver - MultiSourceBorrow receives the collateral
msg.sender // owner - the user who owns the pool shares
)
);
require(success, "Pool withdrawal failed");
}

// Withdraw from staking contract if specified (need to be approved)
if (stakingContractAddress != address(0) && stakingWithdrawAmount > 0) {
(bool success, ) = stakingContractAddress.call(
abi.encodeWithSignature("withdraw(uint256)", stakingWithdrawAmount)
);
require(success, "Staking withdrawal failed");
}



//transfer all of the collateral to the borrower before the loan is accepted on their behalf
TransferHelper.safeTransfer (
_acceptCommitmentArgs.collateralTokenAddress,
msg.sender,
_acceptCommitmentArgs.collateralAmount + poolWithdrawAmount + stakingWithdrawAmount
);



balanceBefore = IERC20(principalTokenAddress).balanceOf(address(this));

// Accept commitment based on type
if (_acceptCommitmentArgs.smartCommitmentAddress != address(0)) {
// Borrow using the smart commitment forwarder
bidId_ = _acceptSmartCommitmentWithRecipient(
_commitmentForwarder,
_acceptCommitmentArgs
);
} else {
// Borrow using the LenderCommitmentForwarder
bidId_ = _acceptCommitmentWithRecipient(
_commitmentForwarder,
_acceptCommitmentArgs
);
}

uint256 balanceAfter = IERC20(principalTokenAddress).balanceOf(address(this));
uint256 fundsRemaining = balanceAfter - balanceBefore;

// Transfer remaining funds to recipient
if (fundsRemaining > 0) {
TransferHelper.safeTransfer(principalTokenAddress, recipient, fundsRemaining);
}

// emit CommitmentAcceptedWithReward( bidId_, _recipient, principalTokenAddress, fundsRemaining, _reward, _rewardRecipient , _atmId);


}


function _acceptSmartCommitmentWithRecipient(
address _smartCommitmentForwarder,
AcceptCommitmentArgs calldata _acceptCommitmentArgs


) internal returns (uint256 bidId_) {

bytes memory responseData = address(_smartCommitmentForwarder)
.functionCall(
abi.encodePacked(
abi.encodeWithSelector(
ISmartCommitmentForwarder
.acceptSmartCommitmentWithRecipient
.selector,
_acceptCommitmentArgs.smartCommitmentAddress,
_acceptCommitmentArgs.principalAmount,
_acceptCommitmentArgs.collateralAmount,
_acceptCommitmentArgs.collateralTokenId,
_acceptCommitmentArgs.collateralTokenAddress,
address(this),
_acceptCommitmentArgs.interestRate,
_acceptCommitmentArgs.loanDuration
),
msg.sender // borrower
)
);


(bidId_) = abi.decode(responseData, (uint256));



}



function _acceptCommitmentWithRecipient(
address _commitmentForwarder,
AcceptCommitmentArgs calldata _acceptCommitmentArgs


) internal returns (uint256 bidId_) {

bytes memory responseData = address(_commitmentForwarder)
.functionCall(
abi.encodePacked(
abi.encodeWithSelector(
ILenderCommitmentForwarder
.acceptCommitmentWithRecipient
.selector,
_acceptCommitmentArgs.commitmentId,
_acceptCommitmentArgs.principalAmount,
_acceptCommitmentArgs.collateralAmount,
_acceptCommitmentArgs.collateralTokenId,
_acceptCommitmentArgs.collateralTokenAddress,
address(this),
_acceptCommitmentArgs.interestRate,
_acceptCommitmentArgs.loanDuration
),
msg.sender //borrower
)
);

(bidId_) = abi.decode(responseData, (uint256));


}


/**
* @notice Fetches the protocol fee percentage from the Teller V2 protocol.
* @return The protocol fee percentage as defined in the Teller V2 protocol.
*/
function _getProtocolFeePct() internal view returns (uint16) {
return IProtocolFee(address(TELLER_V2)).protocolFee();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ pragma solidity >=0.8.0 <0.9.0;
// SPDX-License-Identifier: MIT


import "forge-std/console.sol";
//import "forge-std/console.sol";


import {IUniswapPricingLibrary} from "../interfaces/IUniswapPricingLibrary.sol";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ pragma solidity >=0.8.0 <0.9.0;
// SPDX-License-Identifier: MIT


import "forge-std/console.sol";


import {IUniswapPricingLibrary} from "../interfaces/IUniswapPricingLibrary.sol";


Expand Down Expand Up @@ -51,11 +49,7 @@ contract UniswapPricingHelper
poolRoutes[1]
);


console.log("ratio");
console.logUint(pool0PriceRatio);
console.logUint(pool1PriceRatio);


return
FullMath.mulDiv(
pool0PriceRatio,
Expand Down
Loading