Skip to content
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
2 changes: 1 addition & 1 deletion contracts/abstract/RegistryAware.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ uint constant PAUSE_RAMM = 1 << 1; // 2
uint constant PAUSE_SWAPS = 1 << 2; // 4
uint constant PAUSE_MEMBERSHIP = 1 << 3; // 8
uint constant PAUSE_ASSESSMENTS = 1 << 4; // 16
uint constant PAUSE_CLAIM_PAYOUTS = 1 << 5; // 32
uint constant PAUSE_CLAIMS = 1 << 5; // 32

contract RegistryAware {

Expand Down
2 changes: 1 addition & 1 deletion contracts/interfaces/IAssessment.sol
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ interface IAssessment {

function getAssessmentDataForProductType(uint productTypeId) external view returns (AssessmentData memory assessmentData);

function getAssessmentResult(uint claimId) external view returns(AssessmentStatus status, uint payoutRedemptionPeriod, uint cooldownEnd);
function getAssessmentResult(uint claimId) external view returns(AssessmentStatus status, uint payoutRedemptionPeriod);

function ballotOf(uint claimId, uint assessorMemberId) external view returns (Ballot memory);

Expand Down
2 changes: 1 addition & 1 deletion contracts/mocks/generic/AssessmentGeneric.sol
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ contract AssessmentGeneric is IAssessment {
revert("Unsupported");
}

function getAssessmentResult(uint) external virtual view returns (AssessmentStatus, uint, uint) {
function getAssessmentResult(uint) external virtual view returns (AssessmentStatus, uint) {
revert("Unsupported");
}

Expand Down
4 changes: 2 additions & 2 deletions contracts/mocks/modules/Claims/CLMockAssessment.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ contract CLMockAssessment is AssessmentGeneric {
_productTypeForClaimId[claimId] = productTypeId;
}

function getAssessmentResult(uint claimId) external override view returns (AssessmentStatus, uint, uint) {
return(_status[claimId], _payoutRedemptionEnd[claimId], _cooldownEnd[claimId]);
function getAssessmentResult(uint claimId) external override view returns (AssessmentStatus, uint) {
return(_status[claimId], _payoutRedemptionEnd[claimId]);
}

function setAssessmentResult(uint claimId, AssessmentStatus status, uint payoutRedemptionEnd, uint cooldownEnd) external {
Expand Down
12 changes: 5 additions & 7 deletions contracts/modules/assessment/Assessment.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@

pragma solidity ^0.8.28;

import "../../libraries/external/EnumerableSet.sol";

import "../../abstract/Multicall.sol";
import "../../interfaces/IAssessment.sol";
import "../../abstract/RegistryAware.sol";
import "../../interfaces/IAssessment.sol";
import "../../libraries/external/EnumerableSet.sol";
import "../../libraries/SafeUintCast.sol";

contract Assessment is IAssessment, RegistryAware, Multicall {
Expand Down Expand Up @@ -263,16 +262,15 @@ contract Assessment is IAssessment, RegistryAware, Multicall {
/// @param claimId The ID of the claim to query
/// @return status Current status of the assessment (VOTING, COOLDOWN, ACCEPTED, DENIED, DRAW)
/// @return payoutRedemptionEnd Timestamp when the payout redemption period ends
/// @return cooldownEnd Timestamp when the cooldown period ends
function getAssessmentResult(uint claimId) override external view returns(AssessmentStatus status, uint payoutRedemptionEnd, uint cooldownEnd) {
function getAssessmentResult(uint claimId) override external view returns(AssessmentStatus status, uint payoutRedemptionEnd) {

Assessment memory assessment = _assessments[claimId];
require(assessment.start != 0, InvalidClaimId());

cooldownEnd = assessment.votingEnd + assessment.cooldownPeriod;
uint cooldownEnd = assessment.votingEnd + assessment.cooldownPeriod;
payoutRedemptionEnd = cooldownEnd + assessment.payoutRedemptionPeriod;

return (_getAssessmentStatus(assessment), payoutRedemptionEnd, cooldownEnd);
return (_getAssessmentStatus(assessment), payoutRedemptionEnd);
}

/// @notice Determines the current status of an assessment based on timing and votes
Expand Down
15 changes: 8 additions & 7 deletions contracts/modules/assessment/Claims.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ pragma solidity ^0.8.28;

import "../../abstract/RegistryAware.sol";
import "../../interfaces/IAssessment.sol";
import "../../interfaces/IClaims.sol";
import "../../interfaces/ICover.sol";
import "../../interfaces/ICoverNFT.sol";
import "../../interfaces/ICoverProducts.sol";
import "../../interfaces/IERC20Detailed.sol";
import "../../interfaces/IClaims.sol";
import "../../interfaces/INXMToken.sol";
import "../../interfaces/IPool.sol";
import "../../interfaces/IRamm.sol";
Expand Down Expand Up @@ -78,12 +78,13 @@ contract Claims is IClaims, RegistryAware {

Claim memory claim = _claims[claimId];

(IAssessment.AssessmentStatus assessmentStatus, uint payoutRedemptionEnd, uint cooldownEnd) = assessment.getAssessmentResult(claimId);
(IAssessment.AssessmentStatus assessmentStatus, uint payoutRedemptionEnd) = assessment.getAssessmentResult(claimId);
(IAssessment.Assessment memory claimAssessment) = assessment.getAssessment(claimId);

CoverData memory coverData = cover.getCoverData(claim.coverId);

uint expiration = coverData.start + coverData.period;
uint cooldownEnd = claimAssessment.votingEnd + claimAssessment.cooldownPeriod;

string memory assetSymbol;
if (claim.coverAsset == 0) {
Expand Down Expand Up @@ -151,7 +152,7 @@ contract Claims is IClaims, RegistryAware {
uint32 coverId,
uint96 requestedAmount,
bytes32 ipfsMetadata
) external payable override onlyMember whenNotPaused(PAUSE_CLAIM_PAYOUTS) returns (Claim memory claim) {
) external payable override onlyMember whenNotPaused(PAUSE_CLAIMS) returns (Claim memory claim) {
require(coverNFT.ownerOf(coverId) == msg.sender, NotCoverOwner());

uint claimId = _nextClaimId++;
Expand All @@ -160,7 +161,7 @@ contract Claims is IClaims, RegistryAware {
uint previousSubmission = lastClaimSubmissionOnCover[coverId];

if (previousSubmission > 0) {
(IAssessment.AssessmentStatus status, uint payoutRedemptionEnd, /* cooldownEnd */) = assessment.getAssessmentResult(previousSubmission);
(IAssessment.AssessmentStatus status, uint payoutRedemptionEnd) = assessment.getAssessmentResult(previousSubmission);

require(
status != IAssessment.AssessmentStatus.VOTING &&
Expand Down Expand Up @@ -236,7 +237,7 @@ contract Claims is IClaims, RegistryAware {
/// @dev Must be the cover NFT owner for the claim and a member can call this function
///
/// @param claimId Claim identifier
function redeemClaimPayout(uint claimId) external override onlyMember whenNotPaused(PAUSE_CLAIM_PAYOUTS) {
function redeemClaimPayout(uint claimId) external override onlyMember whenNotPaused(PAUSE_CLAIMS) {

(Claim memory claim, uint payoutRedemptionEnd) = _validateClaimStatus(claimId, IAssessment.AssessmentStatus.ACCEPTED);

Expand Down Expand Up @@ -266,7 +267,7 @@ contract Claims is IClaims, RegistryAware {
/// @dev Can be called by anyone, but the claim deposit is always transferred to the current cover NFT owner.
///
/// @param claimId The unique identifier of the claim for which the deposit is being retrieved.
function retrieveDeposit(uint claimId) external override whenNotPaused(PAUSE_CLAIM_PAYOUTS) {
function retrieveDeposit(uint claimId) external override whenNotPaused(PAUSE_CLAIMS) {

(Claim memory claim, /* payoutRedemptionEnd */) = _validateClaimStatus(claimId, IAssessment.AssessmentStatus.DRAW);

Expand All @@ -290,7 +291,7 @@ contract Claims is IClaims, RegistryAware {
require(claim.amount > 0, InvalidClaimId());

IAssessment.AssessmentStatus status;
(status, payoutRedemptionEnd, /* cooldownEnd */) = assessment.getAssessmentResult(claimId);
(status, payoutRedemptionEnd) = assessment.getAssessmentResult(claimId);
require(status == expectedStatus, InvalidAssessmentStatus());

return (claim, payoutRedemptionEnd);
Expand Down
2 changes: 1 addition & 1 deletion contracts/modules/governance/Registry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ pragma solidity ^0.8.28;

import "../../abstract/EIP712.sol";
import "../../abstract/RegistryAware.sol";
import "../../interfaces/IRegistry.sol";
import "../../interfaces/INXMMaster.sol";
import "../../interfaces/IRegistry.sol";
import "../../interfaces/ITokenController.sol";
import "../../libraries/SafeUintCast.sol";
import "./UpgradeableProxy.sol";
Expand Down
13 changes: 6 additions & 7 deletions test/unit/Assessment/closeVotingEarly.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,18 +113,15 @@ describe('closeVotingEarly', function () {
const block = await ethers.provider.getBlock(blockNumber);
const expectedVotingEndTime = block?.timestamp;

const assessmentData = await assessment.getAssessmentResult(CLAIM_ID);
const cooldownPeriod = await assessment.payoutCooldown(constants.PRODUCT_TYPE_ID);
const votingEndTime = assessmentData.cooldownEnd - cooldownPeriod;

expect(votingEndTime).to.equal(expectedVotingEndTime);
const assessmentData = await assessment.getAssessment(CLAIM_ID);
expect(assessmentData.votingEnd).to.equal(expectedVotingEndTime);
});

it('should succeed with empty assessor group and result in DRAW status', async function () {
const { contracts, accounts, constants } = await loadFixture(setup);
const { assessment } = contracts;
const [governanceAccount] = accounts.governanceContracts;
const { CLAIM_ID, ASSESSOR_GROUP_ID } = constants;
const { CLAIM_ID, ASSESSOR_GROUP_ID, PRODUCT_TYPE_ID } = constants;

// Remove all assessors from the existing group to make it empty
const assessorMemberIds = await Promise.all(accounts.assessors.map(a => contracts.registry.getMemberId(a.address)));
Expand Down Expand Up @@ -158,9 +155,11 @@ describe('closeVotingEarly', function () {
await setTime(Number(BigInt(closeVotingTimestamp) + BigInt(cooldownPeriod) + 1n));

// Check assessment result after cooldown period
const [status, payoutRedemptionEnd, cooldownEnd] = await assessment.getAssessmentResult(CLAIM_ID);
const [status, payoutRedemptionEnd] = await assessment.getAssessmentResult(CLAIM_ID);

// Verify cooldown end and payout redemption end calculation
const assessmentDataForProductType = await assessment.getAssessmentDataForProductType(PRODUCT_TYPE_ID);
const cooldownEnd = assessmentData.votingEnd + assessmentDataForProductType.cooldownPeriod;
const expectedCooldownEnd = BigInt(closeVotingTimestamp) + BigInt(cooldownPeriod);
expect(cooldownEnd).to.equal(expectedCooldownEnd);

Expand Down
30 changes: 8 additions & 22 deletions test/unit/Assessment/getAssessmentResult.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,11 @@ describe('getAssessmentResult', function () {
const { assessment } = contracts;
const { CLAIM_ID } = constants;

const [status, payoutRedemptionEnd, cooldownEnd] = await assessment.getAssessmentResult(CLAIM_ID);
const [status, payoutRedemptionEnd] = await assessment.getAssessmentResult(CLAIM_ID);
const assessmentData = await assessment.getAssessment(CLAIM_ID);
const expectedCooldownEnd = BigInt(assessmentData.votingEnd) + BigInt(assessmentData.cooldownPeriod);
const expectedPayoutRedemptionEnd = expectedCooldownEnd + BigInt(assessmentData.payoutRedemptionPeriod);

expect(cooldownEnd).to.equal(expectedCooldownEnd);
expect(payoutRedemptionEnd).to.equal(expectedPayoutRedemptionEnd);
expect(status).to.equal(AssessmentStatus.VOTING);
});
Expand All @@ -61,9 +60,7 @@ describe('getAssessmentResult', function () {
// Set time to just after voting ends but before cooldown passes
await setTime(votingEnd + 1n);

const [status, payoutRedemptionEnd, cooldownEnd] = await assessment.getAssessmentResult(CLAIM_ID);

expect(cooldownEnd).to.equal(expectedCooldownEnd);
const [status, payoutRedemptionEnd] = await assessment.getAssessmentResult(CLAIM_ID);
expect(payoutRedemptionEnd).to.equal(expectedPayoutRedemptionEnd);
expect(status).to.equal(AssessmentStatus.COOLDOWN);
});
Expand All @@ -88,8 +85,7 @@ describe('getAssessmentResult', function () {
// Set time past cooldown period
await setTime(expectedCooldownEnd + 1n);

const [status, payoutRedemptionEnd, cooldownEnd] = await assessment.getAssessmentResult(CLAIM_ID);
expect(cooldownEnd).to.equal(expectedCooldownEnd);
const [status, payoutRedemptionEnd] = await assessment.getAssessmentResult(CLAIM_ID);
expect(payoutRedemptionEnd).to.equal(expectedPayoutRedemptionEnd);
expect(status).to.equal(AssessmentStatus.ACCEPTED);
});
Expand All @@ -114,8 +110,7 @@ describe('getAssessmentResult', function () {
// Set time past cooldown period
await setTime(cooldownEndTime + 1n);

const [status, payoutRedemptionEnd, cooldownEnd] = await assessment.getAssessmentResult(CLAIM_ID);
expect(cooldownEnd).to.equal(cooldownEndTime);
const [status, payoutRedemptionEnd] = await assessment.getAssessmentResult(CLAIM_ID);
expect(payoutRedemptionEnd).to.equal(expectedPayoutRedemptionEnd);
expect(status).to.equal(AssessmentStatus.DENIED);
});
Expand All @@ -137,9 +132,7 @@ describe('getAssessmentResult', function () {
// Set time past cooldown period
await setTime(expectedCooldownEnd + 1n);

const [status, payoutRedemptionEnd, cooldownEnd] = await assessment.getAssessmentResult(CLAIM_ID);

expect(cooldownEnd).to.equal(expectedCooldownEnd);
const [status, payoutRedemptionEnd] = await assessment.getAssessmentResult(CLAIM_ID);
expect(payoutRedemptionEnd).to.equal(expectedPayoutRedemptionEnd);
expect(status).to.equal(AssessmentStatus.DRAW);
});
Expand All @@ -158,9 +151,7 @@ describe('getAssessmentResult', function () {
// Set time past cooldown period
await setTime(expectedCooldownEnd + 1n);

const [status, payoutRedemptionEnd, cooldownEnd] = await assessment.getAssessmentResult(CLAIM_ID);

expect(cooldownEnd).to.equal(expectedCooldownEnd);
const [status, payoutRedemptionEnd] = await assessment.getAssessmentResult(CLAIM_ID);
expect(payoutRedemptionEnd).to.equal(expectedPayoutRedemptionEnd);
expect(status).to.equal(AssessmentStatus.DRAW);
});
Expand Down Expand Up @@ -205,8 +196,8 @@ describe('getAssessmentResult', function () {
await claims.connect(coverOwner).submitClaim(COVER_ID_3, ethers.parseEther('1'), IPFS_HASH);

// Should have different values for claims with different product types
const [status2, payoutRedemptionEnd2, cooldownEnd2] = await assessment.getAssessmentResult(CLAIM_ID_2);
const [status3, payoutRedemptionEnd3, cooldownEnd3] = await assessment.getAssessmentResult(CLAIM_ID_3);
const [status2, payoutRedemptionEnd2] = await assessment.getAssessmentResult(CLAIM_ID_2);
const [status3, payoutRedemptionEnd3] = await assessment.getAssessmentResult(CLAIM_ID_3);

expect(status2).to.equal(AssessmentStatus.VOTING);
expect(status3).to.equal(AssessmentStatus.VOTING);
Expand All @@ -222,13 +213,8 @@ describe('getAssessmentResult', function () {
const expectedCooldownEnd3 = BigInt(claimAssessmentData3.votingEnd) + BigInt(productType3CooldownPeriod);
const expectedPayoutRedemptionEnd3 = expectedCooldownEnd3 + BigInt(productType3PayoutRedemptionPeriod);

expect(cooldownEnd2).to.equal(expectedCooldownEnd2);
expect(payoutRedemptionEnd2).to.equal(expectedPayoutRedemptionEnd2);

expect(cooldownEnd3).to.equal(expectedCooldownEnd3);
expect(payoutRedemptionEnd3).to.equal(expectedPayoutRedemptionEnd3);

expect(cooldownEnd2).to.not.equal(cooldownEnd3);
expect(payoutRedemptionEnd2).to.not.equal(payoutRedemptionEnd3);
});
});
Loading