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

Fix token gating #635

Merged
merged 39 commits into from
Jul 6, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
eed3f13
Fix token gating
anajuliabit May 12, 2023
5921565
ExchangeHandlerTest:commitToConditionalOffer
anajuliabit May 15, 2023
31aec22
Fix stack to deep and fix getReceipt unit tests
anajuliabit May 15, 2023
d1ad44f
Add length validation to GroupBase's validateCondition function and u…
anajuliabit May 16, 2023
8676813
Adding missing tests to ExchangeHandler
anajuliabit May 16, 2023
6104cff
Adding missing tests to ExchangeHandler
anajuliabit May 16, 2023
b068a1e
Merge branch 'fix-token-gating' of github.com:bosonprotocol/boson-pro…
anajuliabit May 16, 2023
00b97fb
Fix validation function in GroupBase.sol and add new revert reason in…
anajuliabit May 17, 2023
d0e1cf2
Fix domains tests
anajuliabit May 17, 2023
e760eba
Fix invalid condition parameter checks in GroupHandlerTes
anajuliabit May 17, 2023
382634e
Allow condition with SpecificToken to be used for ERC1155 tokens
anajuliabit May 17, 2023
b9f9070
Fix SnapshopGate tests
anajuliabit May 18, 2023
e09749b
Add tests to validate 1155 with SpecificToken
anajuliabit May 19, 2023
c50622d
Add mising validation to group creation
anajuliabit May 19, 2023
2b8f815
Review changes
anajuliabit May 22, 2023
bf001c8
Increase MAX_SKIPPED
anajuliabit May 23, 2023
934b5b9
Review changes
anajuliabit May 29, 2023
e933c4a
Update MAX_SKIPPED value in Check Code Coverage step of ci.yaml file.
anajuliabit May 30, 2023
cfbe4e6
Merge branch 'main' into fix-token-gating
anajuliabit May 30, 2023
8774854
Removed unnecessary code in ExchangeHandlerFacet.sol
anajuliabit May 30, 2023
5737650
Fix per-address with ERC1155 condition
anajuliabit May 31, 2023
f30b31b
Merge branch 'main' into fix-token-gating
anajuliabit May 31, 2023
9de5f99
Review changes
anajuliabit Jun 1, 2023
1c820c9
Refactor ExchangeHandlerTest and GroupHandlerTest to improve code rea…
anajuliabit Jun 2, 2023
2008253
Allow for more use cases
anajuliabit Jun 2, 2023
14ab5dd
Fixing missing tests and adding natspec comments
anajuliabit Jun 5, 2023
7ae320e
Merge branch 'main' into fix-token-gating
anajuliabit Jun 5, 2023
374545e
Added Contracts CI badge to README.md file.
anajuliabit Jun 5, 2023
2ee5ef4
Remove log
anajuliabit Jun 5, 2023
0e0f4a5
Add token ID validation for threshold evaluation method in ExchangeHa…
anajuliabit Jun 5, 2023
16a05b5
Apply review requests
anajuliabit Jun 6, 2023
52e3595
Merge branch 'main' into fix-token-gating
anajuliabit Jun 6, 2023
f286097
Turn arg to calldata
anajuliabit Jun 6, 2023
eb336b0
Merge branch 'main' into fix-token-gating
anajuliabit Jul 6, 2023
9d9345a
Merge branch 'main' into fix-token-gating
anajuliabit Jul 6, 2023
12595e3
Tidy
anajuliabit Jul 6, 2023
21b2c00
Fix Condition:isValid method
anajuliabit Jul 6, 2023
1cc0b32
Turn alterations on this PR compatible with ether.js 6
anajuliabit Jul 6, 2023
99de86b
Fixing merge conflicts
anajuliabit Jul 6, 2023
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/domain/BosonConstants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ string constant GROUP_HAS_CONDITION = "Offer belongs to a group with a condition
string constant MAX_COMMITS_ADDRESS_REACHED = "Max commits per address reached";
string constant MAX_COMMITS_TOKEN_REACHED = "Max commits per token id reached";
string constant TOKEN_ID_NOT_IN_CONDITION_RANGE = "Token id not in condition range";
string constant INVALID_TOKEN_ID = "ERC1155 requires non-zero tokenId; ERC721 and ERC20 require zero tokenId.";
string constant INVALID_TOKEN_ID = "ERC721 and ERC20 require zero tokenId";

// Revert Reasons: Exchange related
string constant NO_SUCH_EXCHANGE = "No such exchange";
Expand Down
41 changes: 15 additions & 26 deletions contracts/protocol/bases/GroupBase.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;

import "./../../domain/BosonConstants.sol";
import { IBosonGroupEvents } from "../../interfaces/events/IBosonGroupEvents.sol";
import { ProtocolBase } from "./../bases/ProtocolBase.sol";
Expand Down Expand Up @@ -120,7 +121,8 @@ contract GroupBase is ProtocolBase, IBosonGroupEvents {
* @return valid - validity of condition
*
*/
function validateCondition(Condition memory _condition) internal pure returns (bool valid) {
function validateCondition(Condition memory _condition) internal pure returns (bool) {
zajck marked this conversation as resolved.
Show resolved Hide resolved
bool valid = true;
if (_condition.method == EvaluationMethod.None) {
valid = (_condition.tokenAddress == address(0) &&
_condition.tokenId == 0 &&
Expand All @@ -129,40 +131,25 @@ contract GroupBase is ProtocolBase, IBosonGroupEvents {
_condition.length == 0);
} else {
if (_condition.tokenId != 0) {
if (_condition.length == 0) {
return false;
}

// Create local copy so we can use assembly to check for overflow
uint256 tokenId = _condition.tokenId;
uint256 length = _condition.length;
uint256 sum;
assembly {
// Adding and checking for overflow in Assembly
let tmp := add(tokenId, sub(length, 1))
if iszero(lt(tmp, tokenId)) {
sum := tmp
}
}

if (sum == 0) {
return false;
}
valid = _condition.length != 0;
valid = valid && type(uint256).max - _condition.length >= _condition.tokenId;
}

if (_condition.method == EvaluationMethod.Threshold) {
valid = (_condition.tokenAddress != address(0) &&
_condition.maxCommits > 0 &&
_condition.threshold > 0);
valid =
valid &&
(_condition.tokenAddress != address(0) && _condition.maxCommits > 0 && _condition.threshold > 0);

if (_condition.tokenType != TokenType.MultiToken) {
// NonFungibleToken and FungibleToken should not have length and tokenId
valid = valid && _condition.length == 0 && _condition.tokenId == 0;
}
} else {
valid = (_condition.tokenAddress != address(0) &&
_condition.maxCommits > 0 &&
_condition.tokenType != TokenType.FungibleToken); // FungibleToken not allowed for SpecificToken
valid =
valid &&
(_condition.tokenAddress != address(0) &&
_condition.maxCommits > 0 &&
_condition.tokenType != TokenType.FungibleToken); // FungibleToken not allowed for SpecificToken

// SpecificToken with NonFungibleToken should not have threshold
if (_condition.tokenType == TokenType.NonFungibleToken) {
Expand All @@ -173,6 +160,8 @@ contract GroupBase is ProtocolBase, IBosonGroupEvents {
}
}
}

return valid;
}

/**
Expand Down
15 changes: 10 additions & 5 deletions contracts/protocol/facets/ExchangeHandlerFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ contract ExchangeHandlerFacet is IBosonExchangeHandler, BuyerBase, DisputeBase {

require(condition.method != EvaluationMethod.None, GROUP_HAS_NO_CONDITION);

if (condition.length > 1) {
// If condition has length > 1, check that the token id is in range
if (condition.length >= 1) {
// If condition has length >= 1, check that the token id is in range
require(
_tokenId >= condition.tokenId && _tokenId < condition.tokenId + condition.length,
TOKEN_ID_NOT_IN_CONDITION_RANGE
Expand Down Expand Up @@ -208,15 +208,20 @@ contract ExchangeHandlerFacet is IBosonExchangeHandler, BuyerBase, DisputeBase {
// Get the condition
Condition storage condition = fetchCondition(groupId);

uint256 tokenId = 0;

// If is a per-token condition or a per-address condition gated with a 1155 token, make sure the condition is not a range since caller (Boson Voucher) cannot specify the token id
if (
condition.method == EvaluationMethod.SpecificToken ||
(condition.method == EvaluationMethod.Threshold && condition.tokenType == TokenType.MultiToken)
) {
require(condition.length == 1, CANNOT_COMMIT);

// Uses token id from the condition
tokenId = condition.tokenId;
}

bool allow = authorizeCommit(_buyer, condition, groupId, 0);
bool allow = authorizeCommit(_buyer, condition, groupId, tokenId);
require(allow, CANNOT_COMMIT);
}

Expand Down Expand Up @@ -987,7 +992,7 @@ contract ExchangeHandlerFacet is IBosonExchangeHandler, BuyerBase, DisputeBase {

require(commitCount < _condition.maxCommits, MAX_COMMITS_TOKEN_REACHED);

allow = holdsSpecificToken(_buyer, _condition, _condition.length == 1 ? _condition.tokenId : _tokenId);
allow = holdsSpecificToken(_buyer, _condition, _tokenId);

if (allow) {
// Increment number of commits to the group for this token id if they are allowed to commit
Expand All @@ -999,7 +1004,7 @@ contract ExchangeHandlerFacet is IBosonExchangeHandler, BuyerBase, DisputeBase {

require(commitCount < _condition.maxCommits, MAX_COMMITS_ADDRESS_REACHED);

allow = holdsThreshold(_buyer, _condition, _condition.length == 1 ? _condition.tokenId : _tokenId);
allow = holdsThreshold(_buyer, _condition, _tokenId);

if (allow) {
// Increment number of commits to the group for this address if they are allowed to commit
Expand Down
2 changes: 1 addition & 1 deletion scripts/config/revert-reasons.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ exports.RevertReasons = {
GROUP_HAS_NO_CONDITION: "Offer belongs to a group without a condition. Use commitToOffer instead",
GROUP_HAS_CONDITION: "Offer belongs to a group with a condition. Use commitToConditionalOffer instead",
TOKEN_ID_NOT_IN_CONDITION_RANGE: "Token id not in condition range",
INVALID_TOKEN_ID: "ERC1155 requires non-zero tokenId; ERC721 and ERC20 require zero tokenId.",
INVALID_TOKEN_ID: "ERC721 and ERC20 require zero tokenId",

// Account-related
MUST_BE_ACTIVE: "Account must be active",
Expand Down
2 changes: 1 addition & 1 deletion test/example/SnapshotGateTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -896,7 +896,7 @@ describe("SnapshotGate", function () {
// Check that holder cannot commit directly to the offer on the protocol itself
await expect(
exchangeHandler.connect(holder).commitToConditionalOffer(holder.address, offerId, entry.tokenId)
).to.revertedWith("Caller cannot commit");
).to.revertedWith(RevertReasons.CANNOT_COMMIT);
});
});
});
Expand Down
29 changes: 11 additions & 18 deletions test/protocol/ExchangeHandlerTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -915,7 +915,7 @@ describe("IBosonExchangeHandler", function () {
).to.emit(exchangeHandler, "BuyerCommitted");
});

context("Offer is part a group", async function () {
context("Offer is part of a group", async function () {
let groupId;
let offerIds;

Expand Down Expand Up @@ -970,7 +970,7 @@ describe("IBosonExchangeHandler", function () {
);
});

it("Offer is part of a group that enfoces per-address conditions and utilizes ERC1155 tokens with range length == 1", async function () {
it("Offer is part of a group that enforces per-address conditions and utilizes ERC1155 tokens with range length == 1", async function () {
condition = mockCondition({
tokenAddress: foreign1155.address,
threshold: "2",
Expand Down Expand Up @@ -1021,17 +1021,18 @@ describe("IBosonExchangeHandler", function () {
);
});

it("Offer is part of a group that has a per-wallet ERC721 condition", async function () {
it("Offer is part of a group that enforces per-wallet conditions and range length == 1", async function () {
// Required constructor params for Group
groupId = "1";
offerIds = [offerId];

condition = mockCondition({
tokenAddress: foreign721.address,
threshold: "1",
threshold: "0",
maxCommits: "3",
tokenType: TokenType.NonFungibleToken,
method: EvaluationMethod.Threshold,
method: EvaluationMethod.SpecificToken,
length: "1",
});

expect(condition.isValid()).to.be.true;
Expand Down Expand Up @@ -1163,7 +1164,7 @@ describe("IBosonExchangeHandler", function () {
).to.revertedWith(RevertReasons.OFFER_SOLD_OUT);
});

it("Offer is part of a group that has a per-address condition and token is ERC1155", async function () {
it("Offer is part of a group that has a per-address condition and token is ERC1155 but accets any token", async function () {
// Required constructor params for Group
groupId = "1";
offerIds = [offerId];
Expand Down Expand Up @@ -1244,7 +1245,7 @@ describe("IBosonExchangeHandler", function () {
).to.revertedWith(RevertReasons.CANNOT_COMMIT);
});

it("Offer is part a group with a per-token condition with length > 1", async function () {
it("Offer is part of a group with a per-token condition with length > 1", async function () {
// Required constructor params for Group
groupId = "1";
offerIds = [offerId];
Expand All @@ -1255,7 +1256,7 @@ describe("IBosonExchangeHandler", function () {
maxCommits: "3",
tokenType: TokenType.NonFungibleToken, // ERC721
tokenId: "0",
method: EvaluationMethod.SpecificToken, // per-wallet
method: EvaluationMethod.SpecificToken, // per-token
length: "0",
});

Expand Down Expand Up @@ -1565,11 +1566,7 @@ describe("IBosonExchangeHandler", function () {
condition.tokenId = "0";
condition.length = "0";

// remove offer from old group
await groupHandler.connect(assistant).removeOffersFromGroup(groupId, offerIds);

// create new group with new condition
await groupHandler.connect(assistant).createGroup(group, condition);
await groupHandler.connect(assistant).setGroupCondition(group.id, condition);

// mint any token for buyer
tokenId = "123";
Expand Down Expand Up @@ -1676,11 +1673,7 @@ describe("IBosonExchangeHandler", function () {
condition.tokenId = "0";
condition.length = "0";

// remove offer from old group
await groupHandler.connect(assistant).removeOffersFromGroup(groupId, offerIds);

// create new group with new condition
await groupHandler.connect(assistant).createGroup(group, condition);
await groupHandler.connect(assistant).setGroupCondition(group.id, condition);

// mint any token for buyer
tokenId = "123";
Expand Down
2 changes: 1 addition & 1 deletion test/protocol/GroupHandlerTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ describe("IBosonGroupHandler", function () {

it("Condition 'Threshold' with MultiToken has tokenId + length - 1 > max uint256", async function () {
condition.tokenType = TokenType.MultiToken;
condition.tokenId = 2;
condition.tokenId = 1;
condition.length = ethers.constants.MaxUint256;

// Attempt to create the group, expecting revert
Expand Down