Skip to content

Commit

Permalink
fix: keep content hash on reject bid
Browse files Browse the repository at this point in the history
  • Loading branch information
codynhat committed Jun 27, 2023
1 parent 0f588af commit deda5c9
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 11 deletions.
6 changes: 3 additions & 3 deletions contracts/pco-license/facets/CFABasePCOFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ contract CFABasePCOFacet is ICFABasePCO, CFABasePCOFacetModifiers {
* @param bidder Initial bidder
* @param newContributionRate New contribution rate for bid
* @param newForSalePrice Intented new for sale price. Must be within rounding bounds of newContributionRate
* @param contentHash Content hash for parcel content
* @param _contentHash Content hash for parcel content
*/
function initializeBid(
ICFABeneficiary beneficiary,
Expand All @@ -106,7 +106,7 @@ contract CFABasePCOFacet is ICFABasePCO, CFABasePCOFacetModifiers {
address bidder,
int96 newContributionRate,
uint256 newForSalePrice,
bytes calldata contentHash
bytes calldata _contentHash
) external onlyOwner {
LibCFABasePCO._initializeBid(
beneficiary,
Expand All @@ -116,7 +116,7 @@ contract CFABasePCOFacet is ICFABasePCO, CFABasePCOFacetModifiers {
bidder,
newContributionRate,
newForSalePrice,
contentHash
_contentHash
);
}

Expand Down
3 changes: 3 additions & 0 deletions contracts/pco-license/interfaces/ICFABasePCO.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ interface ICFABasePCO {
uint256 forSalePrice
);

/// @notice Emitted when content hash is updated
event PayerContentHashUpdated(address indexed _payer, bytes contentHash);

/**
* @notice Initialize bid.
* - Must be the contract owner
Expand Down
16 changes: 12 additions & 4 deletions contracts/pco-license/libraries/LibCFABasePCO.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ library LibCFABasePCO {
uint256 forSalePrice
);

/// @notice Emitted when content hash is updated
event PayerContentHashUpdated(address indexed _payer, bytes contentHash);

function diamondStorage()
internal
pure
Expand Down Expand Up @@ -208,6 +211,7 @@ library LibCFABasePCO {

emit PayerForSalePriceUpdated(bidder, newForSalePrice);
emit PayerContributionRateUpdated(bidder, newContributionRate);
emit PayerContentHashUpdated(bidder, contentHash);

// Create flow (payer -> license)
cs.cfaV1.createFlowByOperator(
Expand All @@ -225,10 +229,13 @@ library LibCFABasePCO {
);
}

function _editBid(int96 newContributionRate, uint256 newForSalePrice)
internal
{
_editBid(newContributionRate, newForSalePrice, new bytes(0));
function _editBid(
int96 newContributionRate,
uint256 newForSalePrice
) internal {
Bid storage bid = _currentBid();

_editBid(newContributionRate, newForSalePrice, bid.contentHash);
}

function _editBid(
Expand Down Expand Up @@ -273,6 +280,7 @@ library LibCFABasePCO {

emit PayerForSalePriceUpdated(bid.bidder, newForSalePrice);
emit PayerContributionRateUpdated(bid.bidder, newContributionRate);
emit PayerContentHashUpdated(bid.bidder, contentHash);

(, uint256 deposit, , ) = paymentToken.realtimeBalanceOfNow(
address(this)
Expand Down
63 changes: 63 additions & 0 deletions test/pco-license/CFABasePCO.fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,68 @@ const initialized = deployments.createFixture(
}
);

const initializedWithContentHash = deployments.createFixture(
async ({ getNamedAccounts, ethers }) => {
const res = await setup();
const {
basePCOFacet,
mockParamsStore,
mockCFABeneficiary,
mockLicense,
ethersjsSf,
paymentToken,
} = res;

const { user } = await getNamedAccounts();

const { numerator, denominator } = perYearToPerSecondRate(0.1);

mockParamsStore.getPerSecondFeeNumerator.returns(numerator);
mockParamsStore.getPerSecondFeeDenominator.returns(denominator);

const contributionRate = BigNumber.from(100);
const forSalePrice = await rateToPurchasePrice(
mockParamsStore,
contributionRate
);

// Transfer payment token for buffer
const requiredBuffer = await ethersjsSf.cfaV1.contract
.connect(await ethers.getSigner(user))
.getDepositRequiredForFlowRate(paymentToken.address, contributionRate);
const op1 = paymentToken.transfer({
receiver: basePCOFacet.address,
amount: requiredBuffer.toString(),
});
await op1.exec(await ethers.getSigner(user));

// Approve flow creation
const op2 = ethersjsSf.cfaV1.updateFlowOperatorPermissions({
superToken: paymentToken.address,
flowOperator: basePCOFacet.address,
permissions: 1,
flowRateAllowance: contributionRate.toString(),
});
await op2.exec(await ethers.getSigner(user));

const txn = await basePCOFacet[
"initializeBid(address,address,address,uint256,address,int96,uint256,bytes)"
](
mockCFABeneficiary.address,
mockParamsStore.address,
mockLicense.address,
1,
user,
contributionRate,
forSalePrice,
"0x12"
);
await txn.wait();

return res;
}
);

const initializedLarge = deployments.createFixture(
async ({ getNamedAccounts, ethers }) => {
const res = await setup();
Expand Down Expand Up @@ -573,6 +635,7 @@ const afterPayerDelete = deployments.createFixture(
export default {
setup,
initialized,
initializedWithContentHash,
initializedLarge,
initializedWithRealLicense,
initializedExtremeFeeDuring,
Expand Down
6 changes: 6 additions & 0 deletions test/pco-license/CFABasePCOFacet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ describe("CFABasePCOFacet", async function () {
await expect(txn)
.to.emit(basePCOFacet, "PayerForSalePriceUpdated")
.withArgs(user, forSalePrice);
await expect(txn)
.to.emit(basePCOFacet, "PayerContentHashUpdated")
.withArgs(user, "0x");
expect(await basePCOFacet.license()).to.equal(mockLicense.address);
expect(await basePCOFacet.licenseId()).to.equal(1);
expect(await basePCOFacet.payer()).to.equal(user);
Expand Down Expand Up @@ -382,6 +385,9 @@ describe("CFABasePCOFacet", async function () {
await expect(txn)
.to.emit(basePCOFacet, "PayerForSalePriceUpdated")
.withArgs(user, forSalePrice);
await expect(txn)
.to.emit(basePCOFacet, "PayerContentHashUpdated")
.withArgs(user, "0x11");
expect(await basePCOFacet.license()).to.equal(mockLicense.address);
expect(await basePCOFacet.licenseId()).to.equal(1);
expect(await basePCOFacet.payer()).to.equal(user);
Expand Down
2 changes: 1 addition & 1 deletion test/pco-license/CFAPenaltyBid.fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const afterPlaceBid = deployments.createFixture(

const afterPlaceBidWithContentHash = deployments.createFixture(
async ({ getNamedAccounts, ethers }) => {
const res = await BaseFixtures.initialized();
const res = await BaseFixtures.initializedWithContentHash();
const { basePCOFacet, mockParamsStore, ethersjsSf, paymentToken } = res;

const { bidder } = await getNamedAccounts();
Expand Down
67 changes: 67 additions & 0 deletions test/pco-license/CFAPenaltyBidFacet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ describe("CFAPenaltyBidFacet", async function () {
await expect(txn)
.to.emit(basePCOFacet, "PayerForSalePriceUpdated")
.withArgs(user, newForSalePrice);
await expect(txn)
.to.emit(basePCOFacet, "PayerContentHashUpdated")
.withArgs(user, "0x");
expect(await basePCOFacet.payer()).to.equal(user);
expect(await basePCOFacet.contributionRate()).to.equal(
newContributionRate
Expand Down Expand Up @@ -172,6 +175,9 @@ describe("CFAPenaltyBidFacet", async function () {
await expect(txn)
.to.emit(basePCOFacet, "PayerForSalePriceUpdated")
.withArgs(user, newForSalePrice);
await expect(txn)
.to.emit(basePCOFacet, "PayerContentHashUpdated")
.withArgs(user, "0x");
expect(await basePCOFacet.payer()).to.equal(user);
expect(await basePCOFacet.contributionRate()).to.equal(
newContributionRate
Expand Down Expand Up @@ -235,6 +241,9 @@ describe("CFAPenaltyBidFacet", async function () {
await expect(txn)
.to.emit(basePCOFacet, "PayerForSalePriceUpdated")
.withArgs(user, newForSalePrice);
await expect(txn)
.to.emit(basePCOFacet, "PayerContentHashUpdated")
.withArgs(user, "0x");
expect(await basePCOFacet.payer()).to.equal(user);
expect(await basePCOFacet.contributionRate()).to.equal(
newContributionRate
Expand Down Expand Up @@ -1013,6 +1022,9 @@ describe("CFAPenaltyBidFacet", async function () {
await expect(txn)
.to.emit(basePCOFacet, "PayerForSalePriceUpdated")
.withArgs(user, newForSalePrice);
await expect(txn)
.to.emit(basePCOFacet, "PayerContentHashUpdated")
.withArgs(user, "0x12");
expect(await basePCOFacet.payer()).to.equal(user);
expect(await basePCOFacet.contributionRate()).to.equal(
newContributionRate
Expand Down Expand Up @@ -1070,6 +1082,9 @@ describe("CFAPenaltyBidFacet", async function () {
await expect(txn)
.to.emit(basePCOFacet, "PayerForSalePriceUpdated")
.withArgs(user, newForSalePrice);
await expect(txn)
.to.emit(basePCOFacet, "PayerContentHashUpdated")
.withArgs(user, "0x12");
expect(await basePCOFacet.payer()).to.equal(user);
expect(await basePCOFacet.contributionRate()).to.equal(
newContributionRate
Expand Down Expand Up @@ -1137,6 +1152,9 @@ describe("CFAPenaltyBidFacet", async function () {
await expect(txn)
.to.emit(basePCOFacet, "PayerForSalePriceUpdated")
.withArgs(user, newForSalePrice);
await expect(txn)
.to.emit(basePCOFacet, "PayerContentHashUpdated")
.withArgs(user, "0x12");
expect(await basePCOFacet.payer()).to.equal(user);
expect(await basePCOFacet.contributionRate()).to.equal(
newContributionRate
Expand Down Expand Up @@ -3024,6 +3042,55 @@ describe("CFAPenaltyBidFacet", async function () {
await checkAppNetFlow();
});

it("should keep content hash after reject bid", async () => {
const { basePCOFacet, paymentToken, ethersjsSf } =
await CFAPenaltyBidFixtures.afterPlaceBidWithContentHash();

const { user } = await getNamedAccounts();

const penaltyPayment: BigNumber = await basePCOFacet.calculatePenalty();

const existingContributionRate = await basePCOFacet.contributionRate();
const oldPendingBid = await basePCOFacet.pendingBid();
const oldBuffer = await ethersjsSf.cfaV1.contract
.connect(await ethers.getSigner(user))
.getDepositRequiredForFlowRate(
paymentToken.address,
await basePCOFacet.contributionRate()
);
const newBuffer = await ethersjsSf.cfaV1.contract
.connect(await ethers.getSigner(user))
.getDepositRequiredForFlowRate(
paymentToken.address,
oldPendingBid.contributionRate
);

// Approve payment token
const approveOp = paymentToken.approve({
receiver: basePCOFacet.address,
amount: penaltyPayment.add(newBuffer).sub(oldBuffer).toString(),
});
await approveOp.exec(await ethers.getSigner(user));

// Approve flow update
const op = ethersjsSf.cfaV1.updateFlowOperatorPermissions({
superToken: paymentToken.address,
flowOperator: basePCOFacet.address,
permissions: 2,
flowRateAllowance: oldPendingBid.contributionRate
.sub(existingContributionRate)
.toString(),
});
await op.exec(await ethers.getSigner(user));

const txn = await basePCOFacet
.connect(await ethers.getSigner(user))
.rejectBid(oldPendingBid.contributionRate, oldPendingBid.forSalePrice);
await txn.wait();

expect(await basePCOFacet.contentHash()).to.equal("0x12");
});

it("should fail if payer increases flow manually", async () => {
const { basePCOFacet, paymentToken, ethersjsSf } =
await CFAPenaltyBidFixtures.afterPlaceBidAndSurplus();
Expand Down
Loading

0 comments on commit deda5c9

Please sign in to comment.