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 claim condition state for supply claimed by wallet #647

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,20 @@ artifacts/build-info
build/
scripts/reference-scripts
cache/
cache_hardhat/
cache_hardhat-zk/
coverage/
dist/
node_modules/
typechain/
typechain-types/
.parcel-cache/

abi/
contracts/abi/
contracts/README.md
artifacts/
artifacts-zk/
artifacts_forge/
contract_artifacts/

Expand Down
18 changes: 15 additions & 3 deletions contracts/extension/Drop.sol
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@ abstract contract Drop is IDrop {
verifyClaim(activeConditionId, _dropMsgSender(), _quantity, _currency, _pricePerToken, _allowlistProof);

// Update contract state.
bytes32 activeConditionHash = claimCondition.conditionHash[activeConditionId];
claimCondition.conditions[activeConditionId].supplyClaimed += _quantity;
claimCondition.supplyClaimedByWallet[activeConditionId][_dropMsgSender()] += _quantity;
claimCondition.supplyClaimedByWallet[activeConditionHash][_dropMsgSender()] += _quantity;

// If there's a price, collect price.
_collectPriceOnClaim(address(0), _quantity, _currency, _pricePerToken);
Expand Down Expand Up @@ -113,6 +114,13 @@ abstract contract Drop is IDrop {
claimCondition.conditions[newStartIndex + i] = _conditions[i];
claimCondition.conditions[newStartIndex + i].supplyClaimed = supplyClaimedAlready;

bytes32 _conditionHash = claimCondition.conditionHash[newStartIndex + i];
if (_resetClaimEligibility || _conditionHash == bytes32(0)) {
claimCondition.conditionHash[newStartIndex + i] = keccak256(
abi.encodePacked((newStartIndex + i), block.number)
);
}

lastConditionStartTimestamp = _conditions[i].startTimestamp;
}

Expand All @@ -129,11 +137,13 @@ abstract contract Drop is IDrop {
if (_resetClaimEligibility) {
for (uint256 i = existingStartIndex; i < newStartIndex; i++) {
delete claimCondition.conditions[i];
delete claimCondition.conditionHash[i];
}
} else {
if (existingPhaseCount > _conditions.length) {
for (uint256 i = _conditions.length; i < existingPhaseCount; i++) {
delete claimCondition.conditions[newStartIndex + i];
delete claimCondition.conditionHash[newStartIndex + i];
}
}
}
Expand All @@ -151,6 +161,7 @@ abstract contract Drop is IDrop {
AllowlistProof calldata _allowlistProof
) public view virtual returns (bool isOverride) {
ClaimCondition memory currentClaimPhase = claimCondition.conditions[_conditionId];
bytes32 activeConditionHash = claimCondition.conditionHash[_conditionId];
uint256 claimLimit = currentClaimPhase.quantityLimitPerWallet;
uint256 claimPrice = currentClaimPhase.pricePerToken;
address claimCurrency = currentClaimPhase.currency;
Expand Down Expand Up @@ -186,7 +197,7 @@ abstract contract Drop is IDrop {
: claimCurrency;
}

uint256 supplyClaimedByWallet = claimCondition.supplyClaimedByWallet[_conditionId][_claimer];
uint256 supplyClaimedByWallet = claimCondition.supplyClaimedByWallet[activeConditionHash][_claimer];

if (_currency != claimCurrency || _pricePerToken != claimPrice) {
revert DropClaimInvalidTokenPrice(_currency, _pricePerToken, claimCurrency, claimPrice);
Expand Down Expand Up @@ -229,7 +240,8 @@ abstract contract Drop is IDrop {
uint256 _conditionId,
address _claimer
) public view returns (uint256 supplyClaimedByWallet) {
supplyClaimedByWallet = claimCondition.supplyClaimedByWallet[_conditionId][_claimer];
bytes32 _conditionHash = claimCondition.conditionHash[_conditionId];
supplyClaimedByWallet = claimCondition.supplyClaimedByWallet[_conditionHash][_claimer];
}

/*////////////////////////////////////////////////////////////////////
Expand Down
18 changes: 15 additions & 3 deletions contracts/extension/Drop1155.sol
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,9 @@ abstract contract Drop1155 is IDrop1155 {
);

// Update contract state.
bytes32 activeConditionHash = claimCondition[_tokenId].conditionHash[activeConditionId];
claimCondition[_tokenId].conditions[activeConditionId].supplyClaimed += _quantity;
claimCondition[_tokenId].supplyClaimedByWallet[activeConditionId][_dropMsgSender()] += _quantity;
claimCondition[_tokenId].supplyClaimedByWallet[activeConditionHash][_dropMsgSender()] += _quantity;

// If there's a price, collect price.
collectPriceOnClaim(_tokenId, address(0), _quantity, _currency, _pricePerToken);
Expand Down Expand Up @@ -123,6 +124,13 @@ abstract contract Drop1155 is IDrop1155 {
conditionList.conditions[newStartIndex + i] = _conditions[i];
conditionList.conditions[newStartIndex + i].supplyClaimed = supplyClaimedAlready;

bytes32 _conditionHash = conditionList.conditionHash[newStartIndex + i];
if (_resetClaimEligibility || _conditionHash == bytes32(0)) {
conditionList.conditionHash[newStartIndex + i] = keccak256(
abi.encodePacked((newStartIndex + i), block.number)
);
}

lastConditionStartTimestamp = _conditions[i].startTimestamp;
}

Expand All @@ -139,11 +147,13 @@ abstract contract Drop1155 is IDrop1155 {
if (_resetClaimEligibility) {
for (uint256 i = existingStartIndex; i < newStartIndex; i++) {
delete conditionList.conditions[i];
delete conditionList.conditionHash[i];
}
} else {
if (existingPhaseCount > _conditions.length) {
for (uint256 i = _conditions.length; i < existingPhaseCount; i++) {
delete conditionList.conditions[newStartIndex + i];
delete conditionList.conditionHash[newStartIndex + i];
}
}
}
Expand All @@ -162,6 +172,7 @@ abstract contract Drop1155 is IDrop1155 {
AllowlistProof calldata _allowlistProof
) public view virtual returns (bool isOverride) {
ClaimCondition memory currentClaimPhase = claimCondition[_tokenId].conditions[_conditionId];
bytes32 activeConditionHash = claimCondition[_tokenId].conditionHash[_conditionId];
uint256 claimLimit = currentClaimPhase.quantityLimitPerWallet;
uint256 claimPrice = currentClaimPhase.pricePerToken;
address claimCurrency = currentClaimPhase.currency;
Expand Down Expand Up @@ -197,7 +208,7 @@ abstract contract Drop1155 is IDrop1155 {
: claimCurrency;
}

uint256 supplyClaimedByWallet = claimCondition[_tokenId].supplyClaimedByWallet[_conditionId][_claimer];
uint256 supplyClaimedByWallet = claimCondition[_tokenId].supplyClaimedByWallet[activeConditionHash][_claimer];

if (_currency != claimCurrency || _pricePerToken != claimPrice) {
revert DropClaimInvalidTokenPrice(_currency, _pricePerToken, claimCurrency, claimPrice);
Expand Down Expand Up @@ -245,7 +256,8 @@ abstract contract Drop1155 is IDrop1155 {
uint256 _conditionId,
address _claimer
) public view returns (uint256 supplyClaimedByWallet) {
supplyClaimedByWallet = claimCondition[_tokenId].supplyClaimedByWallet[_conditionId][_claimer];
bytes32 _conditionHash = claimCondition[_tokenId].conditionHash[_conditionId];
supplyClaimedByWallet = claimCondition[_tokenId].supplyClaimedByWallet[_conditionHash][_claimer];
}

/*////////////////////////////////////////////////////////////////////
Expand Down
8 changes: 6 additions & 2 deletions contracts/extension/interface/IClaimConditionMultiPhase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,19 @@ interface IClaimConditionMultiPhase is IClaimCondition {
* @param count The total number of phases / claim conditions in the list
* of claim conditions.
*
* @param conditionHash Mapping from numeric claim condition ID to a unique hash.
* Used in supplyClaimedByWallet mapping below.
*
* @param conditions The claim conditions at a given uid. Claim conditions
* are ordered in an ascending order by their `startTimestamp`.
*
* @param supplyClaimedByWallet Map from a claim condition uid and account to supply claimed by account.
* @param supplyClaimedByWallet Map from a claim condition uid/hash and account to supply claimed by account.
*/
struct ClaimConditionList {
uint256 currentStartId;
uint256 count;
mapping(uint256 => bytes32) conditionHash;
mapping(uint256 => ClaimCondition) conditions;
mapping(uint256 => mapping(address => uint256)) supplyClaimedByWallet;
mapping(bytes32 => mapping(address => uint256)) supplyClaimedByWallet;
}
}
20 changes: 17 additions & 3 deletions contracts/extension/upgradeable/Drop.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ abstract contract Drop is IDrop {
verifyClaim(activeConditionId, _dropMsgSender(), _quantity, _currency, _pricePerToken, _allowlistProof);

// Update contract state.
bytes32 activeConditionHash = _dropStorage().claimCondition.conditionHash[activeConditionId];
_dropStorage().claimCondition.conditions[activeConditionId].supplyClaimed += _quantity;
_dropStorage().claimCondition.supplyClaimedByWallet[activeConditionId][_dropMsgSender()] += _quantity;
_dropStorage().claimCondition.supplyClaimedByWallet[activeConditionHash][_dropMsgSender()] += _quantity;

// If there's a price, collect price.
_collectPriceOnClaim(address(0), _quantity, _currency, _pricePerToken);
Expand Down Expand Up @@ -102,6 +103,13 @@ abstract contract Drop is IDrop {
_dropStorage().claimCondition.conditions[newStartIndex + i] = _conditions[i];
_dropStorage().claimCondition.conditions[newStartIndex + i].supplyClaimed = supplyClaimedAlready;

bytes32 _conditionHash = _dropStorage().claimCondition.conditionHash[newStartIndex + i];
if (_resetClaimEligibility || _conditionHash == bytes32(0)) {
_dropStorage().claimCondition.conditionHash[newStartIndex + i] = keccak256(
abi.encodePacked((newStartIndex + i), block.number)
);
}

lastConditionStartTimestamp = _conditions[i].startTimestamp;
}

Expand All @@ -118,11 +126,13 @@ abstract contract Drop is IDrop {
if (_resetClaimEligibility) {
for (uint256 i = existingStartIndex; i < newStartIndex; i++) {
delete _dropStorage().claimCondition.conditions[i];
delete _dropStorage().claimCondition.conditionHash[i];
}
} else {
if (existingPhaseCount > _conditions.length) {
for (uint256 i = _conditions.length; i < existingPhaseCount; i++) {
delete _dropStorage().claimCondition.conditions[newStartIndex + i];
delete _dropStorage().claimCondition.conditionHash[newStartIndex + i];
}
}
}
Expand All @@ -140,6 +150,7 @@ abstract contract Drop is IDrop {
AllowlistProof calldata _allowlistProof
) public view virtual returns (bool isOverride) {
ClaimCondition memory currentClaimPhase = _dropStorage().claimCondition.conditions[_conditionId];
bytes32 activeConditionHash = _dropStorage().claimCondition.conditionHash[_conditionId];
uint256 claimLimit = currentClaimPhase.quantityLimitPerWallet;
uint256 claimPrice = currentClaimPhase.pricePerToken;
address claimCurrency = currentClaimPhase.currency;
Expand Down Expand Up @@ -175,7 +186,9 @@ abstract contract Drop is IDrop {
: claimCurrency;
}

uint256 supplyClaimedByWallet = _dropStorage().claimCondition.supplyClaimedByWallet[_conditionId][_claimer];
uint256 supplyClaimedByWallet = _dropStorage().claimCondition.supplyClaimedByWallet[activeConditionHash][
_claimer
];

if (_currency != claimCurrency || _pricePerToken != claimPrice) {
revert("!PriceOrCurrency");
Expand Down Expand Up @@ -218,7 +231,8 @@ abstract contract Drop is IDrop {
uint256 _conditionId,
address _claimer
) public view returns (uint256 supplyClaimedByWallet) {
supplyClaimedByWallet = _dropStorage().claimCondition.supplyClaimedByWallet[_conditionId][_claimer];
bytes32 _conditionHash = _dropStorage().claimCondition.conditionHash[_conditionId];
supplyClaimedByWallet = _dropStorage().claimCondition.supplyClaimedByWallet[_conditionHash][_claimer];
}

/*////////////////////////////////////////////////////////////////////
Expand Down
5 changes: 4 additions & 1 deletion src/test/sdk/extension/drop/verify-claim/verifyClaim.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@ contract MyDrop is Drop {

function setCondition(ClaimCondition calldata condition, uint256 _conditionId) public {
claimCondition.conditions[_conditionId] = condition;
claimCondition.conditionHash[_conditionId] = keccak256(abi.encodePacked(_conditionId, block.number));
}

function setSupplyClaimedByWallet(uint256 _conditionId, address _wallet, uint256 _supplyClaimed) public {
claimCondition.supplyClaimedByWallet[_conditionId][_wallet] = _supplyClaimed;
bytes32 _conditionHash = keccak256(abi.encodePacked(_conditionId, block.number));
claimCondition.supplyClaimedByWallet[_conditionHash][_wallet] = _supplyClaimed;
}
}

Expand Down Expand Up @@ -406,6 +408,7 @@ contract Drop_VerifyClaim is ExtensionUtilTest {
_currency = address(weth);
_pricePerToken = 2;
_quantity = 1;

vm.expectRevert(
abi.encodeWithSelector(
Drop.DropClaimExceedLimit.selector,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,14 @@ contract MyDropUpg is Drop {

function setCondition(ClaimCondition calldata condition, uint256 _conditionId) public {
_dropStorage().claimCondition.conditions[_conditionId] = condition;
_dropStorage().claimCondition.conditionHash[_conditionId] = keccak256(
abi.encodePacked(_conditionId, block.number)
);
}

function setSupplyClaimedByWallet(uint256 _conditionId, address _wallet, uint256 _supplyClaimed) public {
_dropStorage().claimCondition.supplyClaimedByWallet[_conditionId][_wallet] = _supplyClaimed;
bytes32 _conditionHash = keccak256(abi.encodePacked(_conditionId, block.number));
_dropStorage().claimCondition.supplyClaimedByWallet[_conditionHash][_wallet] = _supplyClaimed;
}
}

Expand Down
Loading