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

added fixes for statemind-171, 173 and 175 #592

Merged
merged 1 commit into from
Aug 10, 2023
Merged
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: 0 additions & 1 deletion contracts/peer-to-peer/AddressRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ contract AddressRegistry is Initializable, Ownable2Step, IAddressRegistry {
address public borrowerGateway;
address public quoteHandler;
address public mysoTokenManager;
address public quotePolicyManager;
address public erc721Wrapper;
address public erc20Wrapper;
mapping(address => bool) public isRegisteredVault;
Expand Down
6 changes: 1 addition & 5 deletions contracts/peer-to-peer/LenderVaultImpl.sol
Original file line number Diff line number Diff line change
Expand Up @@ -414,10 +414,6 @@ contract LenderVaultImpl is
return _loans.length;
}

function totalNumSigners() external view returns (uint256) {
return signers.length;
}

function getTokenBalancesAndLockedAmounts(
address[] calldata tokens
)
Expand All @@ -443,7 +439,7 @@ contract LenderVaultImpl is
}
}

function numSigners() external view returns (uint256) {
function totalNumSigners() external view returns (uint256) {
return signers.length;
}

Expand Down
6 changes: 0 additions & 6 deletions contracts/peer-to-peer/interfaces/IAddressRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -186,12 +186,6 @@ interface IAddressRegistry {
*/
function mysoTokenManager() external view returns (address);

/**
* @notice Returns the address of the quote policy manager
* @return Address of the quote policy manager contract
*/
function quotePolicyManager() external view returns (address);

/**
* @notice Returns boolean flag indicating whether given address is a registered vault
* @param addr Address to check if it is a registered vault
Expand Down
12 changes: 3 additions & 9 deletions contracts/peer-to-peer/interfaces/ILenderVaultImpl.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {DataTypesPeerToPeer} from "../DataTypesPeerToPeer.sol";
interface ILenderVaultImpl {
event AddedSigners(address[] _signers);

event MinNumberOfSignersSet(uint256 numSigners);
event MinNumberOfSignersSet(uint256 minNumSigners);

event RemovedSigner(
address signerRemoved,
Expand Down Expand Up @@ -237,10 +237,10 @@ interface ILenderVaultImpl {
function pendingOwner() external view returns (address);

/**
* @notice function to return number of signers
* @notice function to return the total number of signers
* @return number of signers
*/
function numSigners() external view returns (uint256);
function totalNumSigners() external view returns (uint256);

/**
* @notice function to return unlocked token balances
Expand Down Expand Up @@ -316,10 +316,4 @@ interface ILenderVaultImpl {
* @return total number of loans
*/
function totalNumLoans() external view returns (uint256);

/**
* @notice function returns total number of signers
* @return total number of signers
*/
function totalNumSigners() external view returns (uint256);
}
16 changes: 11 additions & 5 deletions contracts/peer-to-peer/policyManagers/BasicQuotePolicyManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ contract BasicQuotePolicyManager is IQuotePolicyManager {
addressRegistry = _addressRegistry;
}

// @dev: When no global policy is set (default case), all pairs are automatically blocked except
// for those where a pair policy is explicitly set. In the case where a global policy is set,
// all pairs are assumed to be allowed (no blocking).
function setGlobalPolicy(
address lenderVault,
bytes calldata globalPolicyData
Expand All @@ -42,7 +45,6 @@ contract BasicQuotePolicyManager is IQuotePolicyManager {
DataTypesBasicPolicies.GlobalPolicy
memory currGlobalPolicy = _globalQuotingPolicies[lenderVault];
if (
globalPolicy.allowAllPairs == currGlobalPolicy.allowAllPairs &&
globalPolicy.requiresOracle ==
currGlobalPolicy.requiresOracle &&
_equalQuoteBounds(
Expand All @@ -67,6 +69,9 @@ contract BasicQuotePolicyManager is IQuotePolicyManager {
emit GlobalPolicySet(lenderVault, globalPolicyData);
}

// @dev: If no global policy is set, then setting a pair policy allows one to explicitly unblock a specific pair;
// in the other case where a global policy is set, setting a pair policy allows overwriting global policy
// parameters as well as overwriting minimum signer threshold requirements.
function setPairPolicy(
address lenderVault,
address collToken,
Expand Down Expand Up @@ -135,7 +140,7 @@ contract BasicQuotePolicyManager is IQuotePolicyManager {
bool hasPairPolicy = _hasPairQuotingPolicy[lenderVault][
generalQuoteInfo.collToken
][generalQuoteInfo.loanToken];
if (!globalPolicy.allowAllPairs && !hasPairPolicy) {
if (!_hasGlobalQuotingPolicy[lenderVault] && !hasPairPolicy) {
return (false, 0);
}

Expand Down Expand Up @@ -294,10 +299,11 @@ contract BasicQuotePolicyManager is IQuotePolicyManager {
) {
return false;
}
}

if (quoteTuple.upfrontFeePctInBase < quoteBounds.minFee) {
return false;
// @dev: only check upfront fee for loans (can skip for swaps where tenor=0)
if (quoteTuple.upfrontFeePctInBase < quoteBounds.minFee) {
return false;
}
}

return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ library DataTypesBasicPolicies {
}

struct GlobalPolicy {
// Flag indicating if all pairs are allowed (=true) or
// per default only pairs with explicitly defined pair policy (=false)
bool allowAllPairs;
// Flag indicating if an oracle is required for the pair
bool requiresOracle;
// Applicable global bounds
Expand Down
5 changes: 2 additions & 3 deletions test/peer-to-peer/helpers/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,14 +335,13 @@ export type QuoteBounds = {
maxLoanPerCollUnitOrLtv: BigNumber
}

export const encodeGlobalPolicy = (allowAllPairs: boolean, requiresOracle: boolean, quoteBounds: QuoteBounds): string => {
export const encodeGlobalPolicy = (requiresOracle: boolean, quoteBounds: QuoteBounds): string => {
return ethers.utils.defaultAbiCoder.encode(
[
'bool allowAllPairs',
'bool requiresOracle',
'tuple(uint32 minTenor, uint32 maxTenor, uint80 minFee, int80 minApr, uint32 minEarliestRepayTenor, uint128 minLoanPerCollUnitOrLtv, uint128 maxLoanPerCollUnitOrLtv) quoteBounds'
],
[allowAllPairs, requiresOracle, quoteBounds]
[requiresOracle, quoteBounds]
)
}

Expand Down
100 changes: 41 additions & 59 deletions test/peer-to-peer/local-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1807,11 +1807,10 @@ describe('Peer-to-Peer: Local Tests', function () {
)

// reverts when trying to remove with signer idx that is out-of-bounds
let numSigners = Number((await lenderVault.numSigners()).toString())
await expect(lenderVault.connect(lender).removeSigner(borrower.address, numSigners)).to.be.revertedWithCustomError(
lenderVault,
'InvalidArrayIndex'
)
let totalNumSigners = Number((await lenderVault.totalNumSigners()).toString())
await expect(
lenderVault.connect(lender).removeSigner(borrower.address, totalNumSigners)
).to.be.revertedWithCustomError(lenderVault, 'InvalidArrayIndex')

// reverts when trying to remove unknown signer address
await expect(lenderVault.connect(lender).removeSigner(weth.address, 0)).to.be.revertedWithCustomError(
Expand All @@ -1830,10 +1829,10 @@ describe('Peer-to-Peer: Local Tests', function () {
await lenderVault.connect(lender).removeSigner(signerAddr, 0)

// remove all signers (always remove last one to test edge case handling)
numSigners = Number((await lenderVault.numSigners()).toString())
for (let i = 0; i < numSigners; i++) {
const lastSignerAddr = await lenderVault.signers(numSigners - i - 1)
await lenderVault.connect(lender).removeSigner(lastSignerAddr, numSigners - i - 1)
totalNumSigners = Number((await lenderVault.totalNumSigners()).toString())
for (let i = 0; i < totalNumSigners; i++) {
const lastSignerAddr = await lenderVault.signers(totalNumSigners - i - 1)
await lenderVault.connect(lender).removeSigner(lastSignerAddr, totalNumSigners - i - 1)
}

// set borrower whitelist
Expand Down Expand Up @@ -6012,7 +6011,7 @@ describe('Peer-to-Peer: Local Tests', function () {
maxLoanPerCollUnitOrLtv: BASE.div(2)
}

const globalPolicyData = encodeGlobalPolicy(true, false, quoteBounds)
const globalPolicyData = encodeGlobalPolicy(false, quoteBounds)

const pairPolicyData = encodePairPolicy(true, 1, quoteBounds)

Expand Down Expand Up @@ -6084,30 +6083,22 @@ describe('Peer-to-Peer: Local Tests', function () {
await expect(
basicPolicyManager
.connect(lender)
.setGlobalPolicy(
lenderVault.address,
encodeGlobalPolicy(true, false, { ...quoteBounds, minTenor: ONE_DAY.mul(40) })
)
.setGlobalPolicy(lenderVault.address, encodeGlobalPolicy(false, { ...quoteBounds, minTenor: ONE_DAY.mul(40) }))
).to.be.revertedWithCustomError(basicPolicyManager, 'InvalidTenors')

await expect(
basicPolicyManager
.connect(lender)
.setGlobalPolicy(
lenderVault.address,
encodeGlobalPolicy(true, false, { ...quoteBounds, minLoanPerCollUnitOrLtv: BASE })
)
.setGlobalPolicy(lenderVault.address, encodeGlobalPolicy(false, { ...quoteBounds, minLoanPerCollUnitOrLtv: BASE }))
).to.be.revertedWithCustomError(basicPolicyManager, 'InvalidLoanPerCollOrLtv')

await expect(
basicPolicyManager
.connect(lender)
.setGlobalPolicy(lenderVault.address, encodeGlobalPolicy(true, false, { ...quoteBounds, minApr: BASE.mul(-2) }))
.setGlobalPolicy(lenderVault.address, encodeGlobalPolicy(false, { ...quoteBounds, minApr: BASE.mul(-2) }))
).to.be.revertedWithCustomError(basicPolicyManager, 'InvalidMinApr')

await basicPolicyManager
.connect(lender)
.setGlobalPolicy(lenderVault.address, encodeGlobalPolicy(true, true, quoteBounds))
await basicPolicyManager.connect(lender).setGlobalPolicy(lenderVault.address, encodeGlobalPolicy(true, quoteBounds))

// borrow should fail without oracle address
await expect(
Expand All @@ -6118,7 +6109,7 @@ describe('Peer-to-Peer: Local Tests', function () {

await basicPolicyManager
.connect(lender)
.setGlobalPolicy(lenderVault.address, encodeGlobalPolicy(true, false, { ...quoteBounds, minTenor: ONE_DAY.mul(35) }))
.setGlobalPolicy(lenderVault.address, encodeGlobalPolicy(false, { ...quoteBounds, minTenor: ONE_DAY.mul(35) }))

// borrow fail if tenor less than min tenor
await expect(
Expand All @@ -6129,7 +6120,7 @@ describe('Peer-to-Peer: Local Tests', function () {

await basicPolicyManager
.connect(lender)
.setGlobalPolicy(lenderVault.address, encodeGlobalPolicy(true, false, { ...quoteBounds, maxTenor: ONE_DAY.mul(25) }))
.setGlobalPolicy(lenderVault.address, encodeGlobalPolicy(false, { ...quoteBounds, maxTenor: ONE_DAY.mul(25) }))

// borrow fail if tenor greater than max tenor
await expect(
Expand All @@ -6140,10 +6131,7 @@ describe('Peer-to-Peer: Local Tests', function () {

await basicPolicyManager
.connect(lender)
.setGlobalPolicy(
lenderVault.address,
encodeGlobalPolicy(true, false, { ...quoteBounds, minFee: BASE.mul(9).div(10) })
)
.setGlobalPolicy(lenderVault.address, encodeGlobalPolicy(false, { ...quoteBounds, minFee: BASE.mul(9).div(10) }))

// borrow should fail if upfront fee is below min fee
await expect(
Expand All @@ -6154,7 +6142,7 @@ describe('Peer-to-Peer: Local Tests', function () {

await basicPolicyManager
.connect(lender)
.setGlobalPolicy(lenderVault.address, encodeGlobalPolicy(true, false, { ...quoteBounds, minApr: BASE.mul(10) }))
.setGlobalPolicy(lenderVault.address, encodeGlobalPolicy(false, { ...quoteBounds, minApr: BASE.mul(10) }))

// borrow should fail if apr is below min apr
await expect(
Expand All @@ -6163,32 +6151,28 @@ describe('Peer-to-Peer: Local Tests', function () {
.borrowWithOnChainQuote(lenderVault.address, borrowInstructions1, onChainQuote1, quoteTupleIdx1)
).to.be.revertedWithCustomError(quoteHandler, 'QuoteViolatesPolicy')

await basicPolicyManager
.connect(lender)
.setGlobalPolicy(
lenderVault.address,
encodeGlobalPolicy(true, false, {
...quoteBounds,
minLoanPerCollUnitOrLtv: BASE.mul(4).div(5),
maxLoanPerCollUnitOrLtv: BASE.mul(9).div(10)
})
)
await basicPolicyManager.connect(lender).setGlobalPolicy(
lenderVault.address,
encodeGlobalPolicy(false, {
...quoteBounds,
minLoanPerCollUnitOrLtv: BASE.mul(4).div(5),
maxLoanPerCollUnitOrLtv: BASE.mul(9).div(10)
})
)

// borrow should go through even if loanPerCollUnitOrLtv is below minLoanPerCollUnitOrLtv if no oracle required
await borrowerGateway
.connect(borrower)
.borrowWithOnChainQuote(lenderVault.address, borrowInstructions1, onChainQuote1, quoteTupleIdx1)

await basicPolicyManager
.connect(lender)
.setGlobalPolicy(
lenderVault.address,
encodeGlobalPolicy(true, false, {
...quoteBounds,
minLoanPerCollUnitOrLtv: ethers.BigNumber.from(0),
maxLoanPerCollUnitOrLtv: ethers.BigNumber.from(0)
})
)
await basicPolicyManager.connect(lender).setGlobalPolicy(
lenderVault.address,
encodeGlobalPolicy(false, {
...quoteBounds,
minLoanPerCollUnitOrLtv: ethers.BigNumber.from(0),
maxLoanPerCollUnitOrLtv: ethers.BigNumber.from(0)
})
)

// borrow should go through even if loanPerCollUnitOrLtv is above maxLoanPerCollUnitOrLtv if no oracle required
await borrowerGateway
Expand Down Expand Up @@ -6227,16 +6211,14 @@ describe('Peer-to-Peer: Local Tests', function () {
'OnChainQuoteAdded'
)

await basicPolicyManager
.connect(lender)
.setGlobalPolicy(
lenderVault.address,
encodeGlobalPolicy(true, false, {
...quoteBounds,
minApr: BASE.mul(-99).div(100),
minEarliestRepayTenor: ONE_DAY.mul(20)
})
)
await basicPolicyManager.connect(lender).setGlobalPolicy(
lenderVault.address,
encodeGlobalPolicy(false, {
...quoteBounds,
minApr: BASE.mul(-99).div(100),
minEarliestRepayTenor: ONE_DAY.mul(20)
})
)

// borrow with negative interest rate should fail if earliest min repay is too short
await expect(
Expand Down
Loading