Skip to content

Commit

Permalink
Merge pull request #316 from joinzien/prices
Browse files Browse the repository at this point in the history
Switch to discount prices instead of percentages
  • Loading branch information
Zoe Nolan authored Oct 25, 2023
2 parents 2225268 + d472f31 commit fb11439
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 116 deletions.
108 changes: 61 additions & 47 deletions contracts/ExpandedNFT.sol
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,15 @@ contract ExpandedNFT is
// Lifetime pass address
IERC721Upgradeable lifetimePassAddress;

// Annual pass discount
uint256 annualPassDiscount;
// Annual pass price
uint256 annualPassAllowListPrice;
uint256 annualPassGeneralPrice;

// Lifetime pass discount
uint256 lifetimePassDiscount;
uint256 lifetimePassAllowListPrice;
uint256 lifetimePassGeneralPrice;
}

uint256 private constant _HUNDRED_PERCENT_AS_BPS = 10000;

// Artists wallet address
address private _artistWallet;

Expand Down Expand Up @@ -230,14 +230,24 @@ contract ExpandedNFT is
return address(_pricing.lifetimePassAddress);
}

/// @dev returns the Annual pass discount
function getAnnualPassDiscount() public view returns (uint256) {
return _pricing.annualPassDiscount;
/// @dev returns the Annual pass price
function getAnnualPassAllowListPrice() public view returns (uint256) {
return _pricing.annualPassAllowListPrice;
}

/// @dev returns the Annual pass price
function getAnnualPassGeneralPrice() public view returns (uint256) {
return _pricing.annualPassGeneralPrice;
}

/// @dev returns the Lifetime pass discount
function getLifetimePassDiscount() public view returns (uint256) {
return _pricing.lifetimePassDiscount;
/// @dev returns the Lifetime pass price
function getLifetimeAllowListPassPrice() public view returns (uint256) {
return _pricing.lifetimePassAllowListPrice;
}

/// @dev returns the Lifetime pass price
function getLifetimePassGeneralPrice() public view returns (uint256) {
return _pricing.lifetimePassGeneralPrice;
}

/// @dev returns mint limit for the address
Expand Down Expand Up @@ -269,15 +279,41 @@ contract ExpandedNFT is
function allowListed(address wallet) public view returns (bool) {
return _pricing.allowListMinters[wallet];
}

/**
@dev returns the current ETH sales price
based on who can currently mint.
*/
function price() public view returns (uint256){
if (_pricing.whoCanMint == WhoCanMint.ALLOWLIST) {
// Assuming Lifetime passes have a greater or equal discount to the annual pass
if (address(_pricing.lifetimePassAddress) != address(0x0)) {
if (_pricing.lifetimePassAddress.balanceOf(msg.sender) > 0) {
return _pricing.lifetimePassAllowListPrice;
}
}

if (address(_pricing.annualPassAddress) != address(0x0)) {
if (_pricing.annualPassAddress.balanceOf(msg.sender) > 0) {
return _pricing.annualPassAllowListPrice;
}
}

return _pricing.allowListSalePrice;
} else if (_pricing.whoCanMint == WhoCanMint.ANYONE) {
// Assuming Lifetime passes have a greater or equal discount to the annual pass
if (address(_pricing.lifetimePassAddress) != address(0x0)) {
if (_pricing.lifetimePassAddress.balanceOf(msg.sender) > 0) {
return _pricing.lifetimePassGeneralPrice;
}
}

if (address(_pricing.annualPassAddress) != address(0x0)) {
if (_pricing.annualPassAddress.balanceOf(msg.sender) > 0) {
return _pricing.annualPassGeneralPrice;
}
}

return salePrice;
}

Expand Down Expand Up @@ -356,33 +392,6 @@ contract ExpandedNFT is
{
uint256 paymentAmount = price() * numberToBeMinted;

// Assuming Lifetime passes have a greeater or equal discount to the annual pass
if (address(_pricing.lifetimePassAddress) != address(0x0)) {
if (_pricing.lifetimePassAddress.balanceOf(msg.sender) > 0) {
uint256 discount = _HUNDRED_PERCENT_AS_BPS - _pricing.lifetimePassDiscount;
uint256 lifetimePassPaymentAmount = (paymentAmount * discount) / _HUNDRED_PERCENT_AS_BPS;

if (msg.value == lifetimePassPaymentAmount) {
return (true);
}

return (false);
}
}

if (address(_pricing.annualPassAddress) != address(0x0)) {
if (_pricing.annualPassAddress.balanceOf(msg.sender) > 0) {
uint256 discount = _HUNDRED_PERCENT_AS_BPS - _pricing.annualPassDiscount;
uint256 annualPassPaymentAmount = (paymentAmount * discount) / _HUNDRED_PERCENT_AS_BPS;

if (msg.value == annualPassPaymentAmount) {
return (true);
}

return (false);
}
}

if (msg.value == paymentAmount) {
return (true);
}
Expand Down Expand Up @@ -481,18 +490,23 @@ contract ExpandedNFT is
/**
@param annualPassAddress Annual pass ERC721 token address. Can be null if no token is in use.
@param lifetimePassAddress Lifetime pass ERC721 token address. Can be null if no token is in use.
@param annualPassDiscount Annual pass discount in BPS.
@param lifetimePassDiscount Lifetime pass discount in BPS.
@param annualPassAllowListPrice the allowlist price when holding an annual pass
@param annualPassGeneralPrice the general price when holding an annual pass
@param lifetimePassAllowListPrice the allowlist price when holding an lifetime pass
@param lifetimePassGeneralPrice the general price when holding an lifetime pass
@dev Set various pricing related values
*/
function updateDiscounts(address annualPassAddress, address lifetimePassAddress, uint256 annualPassDiscount, uint256 lifetimePassDiscount) external onlyOwner {
require(annualPassDiscount <= _HUNDRED_PERCENT_AS_BPS, "Discount can not be greater than 100%");
require(lifetimePassDiscount <= _HUNDRED_PERCENT_AS_BPS, "Discount can not be greater than 100%");

function updateDiscounts(address annualPassAddress, address lifetimePassAddress,
uint256 annualPassAllowListPrice, uint256 annualPassGeneralPrice,
uint256 lifetimePassAllowListPrice, uint256 lifetimePassGeneralPrice) external onlyOwner {
_pricing.annualPassAddress = IERC721Upgradeable(annualPassAddress);
_pricing.lifetimePassAddress = IERC721Upgradeable(lifetimePassAddress);
_pricing.annualPassDiscount = annualPassDiscount;
_pricing.lifetimePassDiscount = lifetimePassDiscount;

_pricing.annualPassAllowListPrice = annualPassAllowListPrice;
_pricing.annualPassGeneralPrice = annualPassGeneralPrice;

_pricing.lifetimePassAllowListPrice = lifetimePassAllowListPrice;
_pricing.lifetimePassGeneralPrice = lifetimePassGeneralPrice;
}

/**
Expand Down
42 changes: 42 additions & 0 deletions test/AllowlistTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,46 @@ describe("Allow List", () => {
expect((await minterContract.getAllowList()).toString()).to.be.equal([nullAddress].toString());
});

it("Add a multiple wallets and remvoe the first to the allow list", async () => {
expect(await minterContract.allowListed(artistAddress)).to.be.equal(false);

// Add a wallet to the allow list
await minterContract.setAllowListMinters(1, [artistAddress], [true])
expect(await minterContract.allowListed(artistAddress)).to.be.equal(true);
expect(await minterContract.getAllowListCount()).to.be.equal(1);
expect((await minterContract.getAllowList()).toString()).to.be.equal([artistAddress].toString());

await minterContract.setAllowListMinters(1, [signerAddress], [true])
expect(await minterContract.allowListed(signerAddress)).to.be.equal(true);
expect(await minterContract.getAllowListCount()).to.be.equal(2);
expect((await minterContract.getAllowList()).toString()).to.be.equal([artistAddress, signerAddress].toString());

// Remove a wallet to the allow list
await minterContract.setAllowListMinters(1, [artistAddress], [false])
expect(await minterContract.allowListed(artistAddress)).to.be.equal(false);
expect(await minterContract.getAllowListCount()).to.be.equal(1);
expect((await minterContract.getAllowList()).toString()).to.be.equal([nullAddress, signerAddress].toString());
});

it("Add a multiple wallets and remvoe the second to the allow list", async () => {
expect(await minterContract.allowListed(artistAddress)).to.be.equal(false);

// Add a wallet to the allow list
await minterContract.setAllowListMinters(1, [artistAddress], [true])
expect(await minterContract.allowListed(artistAddress)).to.be.equal(true);
expect(await minterContract.getAllowListCount()).to.be.equal(1);
expect((await minterContract.getAllowList()).toString()).to.be.equal([artistAddress].toString());

await minterContract.setAllowListMinters(1, [signerAddress], [true])
expect(await minterContract.allowListed(signerAddress)).to.be.equal(true);
expect(await minterContract.getAllowListCount()).to.be.equal(2);
expect((await minterContract.getAllowList()).toString()).to.be.equal([artistAddress, signerAddress].toString());

// Remove a wallet to the allow list
await minterContract.setAllowListMinters(1, [signerAddress], [false])
expect(await minterContract.allowListed(signerAddress)).to.be.equal(false);
expect(await minterContract.getAllowListCount()).to.be.equal(1);
expect((await minterContract.getAllowList()).toString()).to.be.equal([artistAddress, nullAddress].toString());
});

});
32 changes: 25 additions & 7 deletions test/DiscountTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ describe("Discounts", () => {
const mintCostAllowlist = ethers.utils.parseEther("0.4");
const mintCostGeneral = ethers.utils.parseEther("0.8");

const hundreadPercentInBps = 10000;
const annualPassDiscountBps = 2500;
const lifetimePassDiscountBps = 5000;
const mintCostAllowlistLifetimePass = ethers.utils.parseEther("0.2");
const mintCostGeneralLifetimePass = ethers.utils.parseEther("0.4");

const mintCostAllowlistAnnualPass = ethers.utils.parseEther("0.3");
const mintCostGeneralAnnualPass = ethers.utils.parseEther("0.6");

beforeEach(async () => {
signer = (await ethers.getSigners())[0];
Expand Down Expand Up @@ -84,13 +86,22 @@ describe("Discounts", () => {
lifetimePassContract.initialize();

await minterContract.setPricing(10, 500, mintCostAllowlist, mintCostGeneral, 2, 1);
await minterContract.updateDiscounts(annualPassContract.address, lifetimePassContract.address, annualPassDiscountBps, lifetimePassDiscountBps);
const mintCostAllowlistLifetimePass = ethers.utils.parseEther("0.2");
const mintCostGeneralLifetimePass = ethers.utils.parseEther("0.4");

const mintCostAllowlistAnnualPass = ethers.utils.parseEther("0.3");
const mintCostGeneralAnnualPass = ethers.utils.parseEther("0.6");


await minterContract.updateDiscounts(annualPassContract.address, lifetimePassContract.address,
mintCostAllowlistAnnualPass, mintCostGeneralAnnualPass,
mintCostAllowlistLifetimePass, mintCostGeneralLifetimePass);
});

it("A non pass holder can not mint while the drop is not for sale", async () => {
await minterContract.setAllowedMinter(0);

await expect(minterContract.connect(user).mintEditions([signerAddress], { value: ethers.utils.parseEther("0.4") })).to.be.revertedWith("Needs to be an allowed minter");
await expect(minterContract.connect(user).mintEditions([signerAddress], { value: ethers.utils.parseEther("0.4") })).to.be.revertedWith("Needs to be an allowed minter");
});

it("A non pass holder can not mint while the drop is only for sale to allow listed wallets", async () => {
Expand Down Expand Up @@ -342,7 +353,7 @@ describe("Discounts", () => {
});

it("A pass holder can mint for free with 100% discount", async () => {
await minterContract.updateDiscounts(annualPassContract.address, lifetimePassContract.address, hundreadPercentInBps, hundreadPercentInBps);
await minterContract.updateDiscounts(annualPassContract.address, lifetimePassContract.address, 0, 0, 0, 0);

await annualPassContract.connect(user).mint(userAddress);
await minterContract.setAllowedMinter(2);
Expand All @@ -357,8 +368,15 @@ describe("Discounts", () => {
});

it("A pass holder can mint for the standard cost with 0% discount", async () => {
await minterContract.updateDiscounts(annualPassContract.address, lifetimePassContract.address, 0, 0);
const mintCostAllowlistLifetimePass = ethers.utils.parseEther("0.4");
const mintCostGeneralLifetimePass = ethers.utils.parseEther("0.8");

const mintCostAllowlistAnnualPass = ethers.utils.parseEther("0.4");
const mintCostGeneralAnnualPass = ethers.utils.parseEther("0.8");

await minterContract.updateDiscounts(annualPassContract.address, lifetimePassContract.address, mintCostAllowlistAnnualPass, mintCostGeneralAnnualPass,
mintCostAllowlistLifetimePass, mintCostGeneralLifetimePass);

await annualPassContract.connect(user).mint(userAddress);
await minterContract.setAllowedMinter(2);

Expand Down
Loading

0 comments on commit fb11439

Please sign in to comment.