Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

commitment allowlist managers #44

Draft
wants to merge 17 commits into
base: develop
Choose a base branch
from
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
**/node_modules

packages/contracts/generated
packages/contracts/lib/forge-std
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we want to include this in the repo - this is a link to the commit used by the submodule

packages/contracts/deployments/hardhat
packages/contracts/deployments/tenderly
packages/contracts/deployments/localhost
Expand Down
91 changes: 56 additions & 35 deletions packages/contracts/contracts/LenderCommitmentForwarder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import "./TellerV2MarketForwarder.sol";

// Interfaces
import "./interfaces/ICollateralManager.sol";

import "./interfaces/allowlist/IAllowlistManager.sol";
import "./interfaces/allowlist/IEnumerableSetAllowlist.sol";

import "./interfaces/ILenderCommitmentForwarder.sol";

import { Collateral, CollateralType } from "./interfaces/escrow/ICollateralEscrowV1.sol";

import "@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol";
Expand All @@ -14,8 +20,11 @@ import "@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeab
import { MathUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";

contract LenderCommitmentForwarder is TellerV2MarketForwarder {
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;



contract LenderCommitmentForwarder is TellerV2MarketForwarder, ILenderCommitmentForwarder {
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;

enum CommitmentCollateralType {
NONE, // no collateral required
Expand Down Expand Up @@ -59,7 +68,9 @@ contract LenderCommitmentForwarder is TellerV2MarketForwarder {
uint256 commitmentCount;

mapping(uint256 => EnumerableSetUpgradeable.AddressSet)
internal commitmentBorrowersList;
internal __commitmentBorrowersList; //DEPRECATED -> moved to manager

mapping(uint256 => address) public commitmentAllowListManagers;

/**
* @notice This event is emitted when a lender's commitment is created.
Expand Down Expand Up @@ -92,6 +103,11 @@ contract LenderCommitmentForwarder is TellerV2MarketForwarder {
uint256 tokenAmount
);

event UpdatedAllowlistManager(
uint256 indexed commitmentId,
address manager
);

/**
* @notice This event is emitted when the allowed borrowers for a commitment is updated.
* @param commitmentId The id of the commitment that was updated.
Expand Down Expand Up @@ -134,6 +150,11 @@ contract LenderCommitmentForwarder is TellerV2MarketForwarder {
_;
}


function getCommitmentLender(uint256 _commitmentId) public returns (address lender_){
lender_ = commitments[_commitmentId].lender;
}

function validateCommitment(Commitment storage _commitment) internal {
require(
_commitment.expiration > uint32(block.timestamp),
Expand Down Expand Up @@ -171,12 +192,12 @@ contract LenderCommitmentForwarder is TellerV2MarketForwarder {
/**
* @notice Creates a loan commitment from a lender for a market.
* @param _commitment The new commitment data expressed as a struct
* @param _borrowerAddressList The array of borrowers that are allowed to accept loans using this commitment
* @param borrowerAllowlistManager The address of the allowlist contract
* @return commitmentId_ returns the commitmentId for the created commitment
*/
function createCommitment(
Commitment calldata _commitment,
address[] calldata _borrowerAddressList
address borrowerAllowlistManager
) public returns (uint256 commitmentId_) {
commitmentId_ = commitmentCount++;

Expand All @@ -186,10 +207,11 @@ contract LenderCommitmentForwarder is TellerV2MarketForwarder {
);

commitments[commitmentId_] = _commitment;
commitmentAllowListManagers[commitmentId_] = borrowerAllowlistManager;

validateCommitment(commitments[commitmentId_]);

_addBorrowersToCommitmentAllowlist(commitmentId_, _borrowerAddressList);
//_addBorrowersToCommitmentAllowlist(commitmentId_, _borrowerAddressList);

emit CreatedCommitment(
commitmentId_,
Expand All @@ -198,6 +220,11 @@ contract LenderCommitmentForwarder is TellerV2MarketForwarder {
_commitment.principalTokenAddress,
_commitment.maxPrincipal
);

emit UpdatedAllowlistManager(
commitmentId_,
borrowerAllowlistManager
);
}

/**
Expand Down Expand Up @@ -232,33 +259,16 @@ contract LenderCommitmentForwarder is TellerV2MarketForwarder {
);
}

/**
* @notice Updates the borrowers allowed to accept a commitment
* @param _commitmentId The Id of the commitment to update.
* @param _borrowerAddressList The array of borrowers that are allowed to accept loans using this commitment
*/
function updateCommitmentBorrowers(
function updateAllowlistManager(
uint256 _commitmentId,
address[] calldata _borrowerAddressList
address _allowlistManager
) public commitmentLender(_commitmentId) {
delete commitmentBorrowersList[_commitmentId];
_addBorrowersToCommitmentAllowlist(_commitmentId, _borrowerAddressList);
}

commitmentAllowListManagers[_commitmentId] = _allowlistManager;

/**
* @notice Adds a borrower to the allowlist for a commmitment.
* @param _commitmentId The id of the commitment that will allow the new borrower
* @param _borrowerArray the address array of the borrowers that will be allowed to accept loans using the commitment
*/
function _addBorrowersToCommitmentAllowlist(
uint256 _commitmentId,
address[] calldata _borrowerArray
) internal {
for (uint256 i = 0; i < _borrowerArray.length; i++) {
commitmentBorrowersList[_commitmentId].add(_borrowerArray[i]);
}
emit UpdatedCommitmentBorrowers(_commitmentId);
emit UpdatedAllowlistManager(_commitmentId,_allowlistManager);
}


/**
* @notice Removes the commitment of a lender to a market.
Expand All @@ -269,7 +279,7 @@ contract LenderCommitmentForwarder is TellerV2MarketForwarder {
commitmentLender(_commitmentId)
{
delete commitments[_commitmentId];
delete commitmentBorrowersList[_commitmentId];
//delete commitmentBorrowersList[_commitmentId];
emit DeletedCommitment(_commitmentId);
}

Expand Down Expand Up @@ -326,10 +336,19 @@ contract LenderCommitmentForwarder is TellerV2MarketForwarder {
);

require(
commitmentBorrowersList[_commitmentId].length() == 0 ||
commitmentBorrowersList[_commitmentId].contains(borrower),
"unauthorized commitment borrower"
__commitmentBorrowersList[_commitmentId].length() == 0 ||
commitmentAllowListManagers[_commitmentId] != address(0),
"Commitments with legacy borrower list must now set an allow list manager"
);


require(commitmentAllowListManagers[_commitmentId] == address(0) ||
IAllowlistManager(commitmentAllowListManagers[_commitmentId]).addressIsAllowed(
_commitmentId, borrower
),
"Borrower not allowlisted"
);


if (_principalAmount > commitment.maxPrincipal) {
revert InsufficientCommitmentAllocation({
Expand Down Expand Up @@ -398,6 +417,8 @@ contract LenderCommitmentForwarder is TellerV2MarketForwarder {
);
}



/**
* @notice Calculate the amount of collateral required to borrow a loan with _principalAmount of principal
* @param _principalAmount The amount of currency to borrow for the loan.
Expand Down Expand Up @@ -446,13 +467,13 @@ contract LenderCommitmentForwarder is TellerV2MarketForwarder {
* @param _commitmentId The commitment id for the commitment to query.
* @return borrowers_ An array of addresses restricted to accept the commitment. Empty array means unrestricted.
*/
function getCommitmentBorrowers(uint256 _commitmentId)
/* function getCommitmentBorrowers(uint256 _commitmentId)
external
view
returns (address[] memory borrowers_)
{
borrowers_ = commitmentBorrowersList[_commitmentId].values();
}
}*/

/**
* @notice Internal function to submit a bid to the lending protocol using a commitment
Expand Down
36 changes: 36 additions & 0 deletions packages/contracts/contracts/allowlist/ERC721Allowlist.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@

pragma solidity >=0.8.0 <0.9.0;
// SPDX-License-Identifier: MIT
import "../interfaces/allowlist/IAllowlistManager.sol";

import "../interfaces/allowlist/IERC721Allowlist.sol";

import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";

contract ERC721Allowlist is IAllowlistManager,IERC721Allowlist {

event UpdatedAllowList(uint256 commitmentId);


IERC721Upgradeable public immutable accessToken; //IERC721



constructor(address _accessToken){
accessToken = IERC721Upgradeable(_accessToken);
}

function addressIsAllowed(uint256 _commitmentId, address _account) public virtual returns (bool) {
return accessToken.balanceOf(_account) >= 1;
}

/*
function getAllowedAddresses(uint256 _commitmentId)
public
view
returns (address[] memory borrowers_)
{
borrowers_ = allowList[_commitmentId].values();
}*/

}
72 changes: 72 additions & 0 deletions packages/contracts/contracts/allowlist/EnumerableSetAllowlist.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
pragma solidity >=0.8.0 <0.9.0;
// SPDX-License-Identifier: MIT

import "../interfaces/allowlist/IAllowlistManager.sol";
import "../interfaces/allowlist/IEnumerableSetAllowlist.sol";

import "../interfaces/ILenderCommitmentForwarder.sol";

import "@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol";


contract EnumerableSetAllowlist is IAllowlistManager,IEnumerableSetAllowlist {
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;

event UpdatedAllowList(uint256 commitmentId);

address public immutable commitmentManager;

mapping(uint256 => EnumerableSetUpgradeable.AddressSet) internal allowList;

modifier onlyCommitmentOwner(uint256 _commitmentId){
require(msg.sender == ILenderCommitmentForwarder(commitmentManager).getCommitmentLender(_commitmentId),"Must be the lender of the commitment.");
_;
}

constructor(address _commitmentManager){
commitmentManager = _commitmentManager;
}


function setAllowlist(
uint256 _commitmentId,
address[] calldata _addressList
) public
onlyCommitmentOwner(_commitmentId)
{

delete allowList[_commitmentId];
_addToAllowlist(_commitmentId, _addressList);
}


/**
* @notice Adds a addresses to the allowlist for a commmitment.
* @param _commitmentId The id of the commitment that will allow the new borrower
* @param _addressList the address array that will be allowed to accept loans using the commitment
*/
function _addToAllowlist(
uint256 _commitmentId,
address[] calldata _addressList
) internal virtual {

for (uint256 i = 0; i < _addressList.length; i++) {
allowList[_commitmentId].add(_addressList[i]);
}
emit UpdatedAllowList(_commitmentId);
}


function addressIsAllowed(uint256 _commitmentId, address _account) public virtual returns (bool) {
return allowList[_commitmentId].contains(_account);
}

function getAllowedAddresses(uint256 _commitmentId)
public
view
returns (address[] memory borrowers_)
{
borrowers_ = allowList[_commitmentId].values();
}

}
20 changes: 20 additions & 0 deletions packages/contracts/contracts/allowlist/OpenAllowlist.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

pragma solidity >=0.8.0 <0.9.0;
// SPDX-License-Identifier: MIT
import "../interfaces/allowlist/IAllowlistManager.sol";


contract OpenAllowlist is IAllowlistManager {

event UpdatedAllowList(uint256 commitmentId);

constructor( ){

}

function addressIsAllowed(uint256, address) public virtual returns (bool) {
return true;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-Licence-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;


interface ILenderCommitmentForwarder {

function getCommitmentLender(uint256 _commitmentId) external returns (address lender_);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@



interface IAllowlistManager {


function addressIsAllowed(uint256 _commitmentId,address _account) external returns (bool allowed_) ;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@


interface IERC721Allowlist {


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@



interface IEnumerableSetAllowlist {

function setAllowlist(
uint256 _commitmentId,
address[] calldata _addressList
) external;

}
11 changes: 11 additions & 0 deletions packages/contracts/contracts/mock/AllowlistManagerMock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

import "../interfaces/allowlist/IAllowlistManager.sol";
contract AllowlistManagerMock is IAllowlistManager {


function addressIsAllowed(uint256 _commitmentId, address _account) public returns (bool _allowed) {
return true;
}


}
Loading