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

SuperMinterV1_1 et al. #296

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d0e97dc
Prep files
Vectorized Nov 17, 2023
814e6f2
Reinstall multicaller
Vectorized Nov 17, 2023
56ecca9
forge install: multicaller
Vectorized Nov 17, 2023
289f5f5
Add LibMulticaller.senderOrSigner support
Vectorized Nov 17, 2023
767e950
Tidy
Vectorized Nov 17, 2023
51a192b
freeMintIncentive -> cheapMintIncentive
Vectorized Nov 24, 2023
83f02ac
Add comment on the two types of affiliate fees
Vectorized Nov 24, 2023
00273e4
Remove first collector incentives
Vectorized Nov 25, 2023
e993498
Add more comments and use checked math in mintTo
Vectorized Dec 1, 2023
9df9a7a
Add finalAffiliateIncentive to Minted log. Change finalCheapMintFee -…
Vectorized Dec 1, 2023
9d7530b
Add platform airdrop functionality to SuperMinterV1_1 (#298)
Vectorized Dec 15, 2023
ab5d9c3
Create modern-shirts-try.md
vigneshka Dec 15, 2023
9dc3992
pin version for typechain
vigneshka Dec 15, 2023
8e48a58
tweak ci
vigneshka Dec 15, 2023
3e86b2b
more ci tweaks
vigneshka Dec 15, 2023
babe37c
add back foundry
vigneshka Dec 15, 2023
12c912f
Merge branch 'main' of github.com:soundxyz/sound-protocol into vector…
vigneshka Dec 15, 2023
78f8bd9
bump
vigneshka Dec 15, 2023
4abef49
Merge branch 'main' of github.com:soundxyz/sound-protocol into vector…
vigneshka Dec 15, 2023
44373d5
bump typechain
vigneshka Dec 15, 2023
815ce5b
Merge branch 'main' of github.com:soundxyz/sound-protocol into vector…
vigneshka Dec 15, 2023
df00147
Implement fee changes (#299)
Vectorized Dec 18, 2023
30e8987
Update modern-shirts-try.md
vigneshka Dec 18, 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
5 changes: 5 additions & 0 deletions .changeset/modern-shirts-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@soundxyz/sound-protocol": minor
---

SuperMinterV2 et al.
30 changes: 14 additions & 16 deletions .github/workflows/canary.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
name: Canary Release

on:
push:
workflow_dispatch:

env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

jobs:
publish-canary:
name: Publish Canary
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@master
uses: actions/checkout@v4
with:
# This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits
fetch-depth: 0
Expand All @@ -19,28 +23,22 @@ jobs:
with:
version: nightly

- name: Setup Node.js 14.x
uses: actions/setup-node@master
- name: Setup PNPM
uses: pnpm/action-setup@v2.2.4
with:
version: latest

- name: Setup Node v18
uses: actions/setup-node@v4
with:
node-version: 16.x
node-version: 18
cache: 'pnpm'

- name: Setup NPM credentials
run: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Cache pnpm modules
uses: actions/cache@v2
env:
cache-name: cache-pnpm-modules
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-v2-${{ hashFiles('./pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-v2
- name: install pnpm
run: npm i pnpm@latest -g

- name: Install Dependencies
run: pnpm i

Expand Down
10 changes: 6 additions & 4 deletions .github/workflows/danger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ jobs:
- name: Checkout
uses: actions/checkout@v2

- uses: pnpm/action-setup@v2.0.1
- name: Setup PNPM
uses: pnpm/action-setup@v2.2.4
with:
version: latest
- name: Setup Node v16
uses: actions/setup-node@v2

- name: Setup Node v18
uses: actions/setup-node@v4
with:
node-version: '16.x'
node-version: 18
cache: 'pnpm'

- name: Run Danger JS
Expand Down
7 changes: 3 additions & 4 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,10 @@ jobs:
with:
version: latest

- name: Set up Node.js
uses: actions/setup-node@v3
- name: Setup Node v18
uses: actions/setup-node@v4
with:
node-version: 16.16.0
cache: 'pnpm'
node-version: 18

- name: Install Node.js dependencies
run: pnpm install
Expand Down
102 changes: 53 additions & 49 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,52 +1,56 @@
name: Release

on:
push:
branches:
- main
push:
branches:
- main

jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout Master
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Use Node
uses: actions/setup-node@v2
with:
node-version: "16.x"
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly
- name: Cache pnpm modules
uses: actions/cache@v2
env:
cache-name: cache-pnpm-modules
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-${{ hashFiles('./pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-
- name: install pnpm
run: npm i pnpm@^7.2.1 -g
- name: Install Dependencies
run: pnpm i

- name: Setup NPM credentials
run: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Create Release Pull Request or Publish to npm
id: changesets
uses: dotansimha/changesets-action@v1.3.3
with:
publish: "pnpm release"
commit: "chore(release): update monorepo packages versions"
title: "Upcoming Release Changes"
createGithubReleases: true
githubReleaseName: ${{ steps.vars.outputs.date }}
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v4
with:
# This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits
fetch-depth: 0

- name: Setup PNPM
uses: pnpm/action-setup@v2.2.4
with:
version: latest

- name: Setup Node v18
uses: actions/setup-node@v3
with:
node-version: 18
cache: 'pnpm'

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

- name: Install Dependencies
run: pnpm install --no-frozen-lockfile

- name: Set version variables
id: vars
shell: bash
run: |
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
echo "date=$(date +"%B %d, %Y")" >> $GITHUB_OUTPUT

- name: Create Release Pull Request or Publish to npm
id: changesets
uses: dotansimha/changesets-action@v1.3.3
with:
publish: 'pnpm release'
commit: 'chore(release): update monorepo packages versions'
title: 'Upcoming Release Changes'
createGithubReleases: true
githubReleaseName: ${{ steps.vars.outputs.date }}
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ cache
out*
typechain
dist
create2
.tmp

# Ignores development broadcast logs
/broadcast/**/run-166*.json
Expand All @@ -16,4 +18,4 @@ node_modules
lcov.info
/coverage/*

.DS_Store
.DS_Store
8 changes: 3 additions & 5 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,9 @@
url = https://github.com/chiru-labs/ERC721A-Upgradeable
branch = 05bd2b9993e632ff898472fb6aec6d698a4c6015
ignore = dirty
[submodule "lib/multicaller"]
path = lib/multicaller
url = https://github.com/vectorized/multicaller
branch = main
ignore = dirty
[submodule "lib/solady"]
path = lib/solady
url = https://github.com/vectorized/solady
[submodule "lib/multicaller"]
path = lib/multicaller
url = https://github.com/vectorized/multicaller
4 changes: 4 additions & 0 deletions build_create2_deployments.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,7 @@ generateDeployment "SoundEditionV2";
generateDeployment "SoundCreatorV2";
generateDeployment "SoundOnChainMetadata";
generateDeployment "SoundMetadata";

generateDeployment "SoundEditionV2_1";
generateDeployment "SuperMinterV2";

26 changes: 17 additions & 9 deletions contracts/core/SoundEditionV2_1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ contract SoundEditionV2_1 is ISoundEditionV2_1, ERC721AQueryableUpgradeable, ERC
function initialize(EditionInitialization memory init) public {
// Will revert upon double initialization.
_initializeERC721A(init.name, init.symbol);
_initializeOwner(LibMulticaller.sender());
_initializeOwner(LibMulticaller.senderOrSigner());

_validateRoyaltyBPS(init.royaltyBPS);
_validateFundingRecipient(init.fundingRecipient);
Expand Down Expand Up @@ -219,9 +219,10 @@ contract SoundEditionV2_1 is ISoundEditionV2_1, ERC721AQueryableUpgradeable, ERC
address to,
uint256 quantity
) external payable onlyRolesOrOwner(ADMIN_ROLE | MINTER_ROLE) returns (uint256 fromTokenId) {
fromTokenId = _beforeTieredMint(tier, quantity);
uint32 fromTierTokenIdIndex;
(fromTokenId, fromTierTokenIdIndex) = _beforeTieredMint(tier, quantity);
_batchMint(to, quantity);
emit Minted(tier, to, quantity, fromTokenId);
emit Minted(tier, to, quantity, fromTokenId, fromTierTokenIdIndex);
}

/**
Expand All @@ -231,17 +232,18 @@ contract SoundEditionV2_1 is ISoundEditionV2_1, ERC721AQueryableUpgradeable, ERC
uint8 tier,
address[] calldata to,
uint256 quantity
) external payable onlyRolesOrOwner(ADMIN_ROLE) returns (uint256 fromTokenId) {
) external payable onlyRolesOrOwner(ADMIN_ROLE | MINTER_ROLE) returns (uint256 fromTokenId) {
uint32 fromTierTokenIdIndex;
unchecked {
// Multiplication overflow is not possible due to the max block gas limit.
// If `quantity` is too big (e.g. 2**64), the loop in `_batchMint` will run out of gas.
// If `to.length` is too big (e.g. 2**64), the airdrop mint loop will run out of gas.
fromTokenId = _beforeTieredMint(tier, to.length * quantity);
(fromTokenId, fromTierTokenIdIndex) = _beforeTieredMint(tier, to.length * quantity);
for (uint256 i; i != to.length; ++i) {
_batchMint(to[i], quantity);
}
}
emit Airdropped(tier, to, quantity, fromTokenId);
emit Airdropped(tier, to, quantity, fromTokenId, fromTierTokenIdIndex);
}

/**
Expand Down Expand Up @@ -604,7 +606,7 @@ contract SoundEditionV2_1 is ISoundEditionV2_1, ERC721AQueryableUpgradeable, ERC
unchecked {
uint256 l = stop - start;
uint256 n = tierMinted(tier);
if (LibOps.or(start >= stop, stop > n)) revert InvalidQueryRange();
if (LibOps.or(start > stop, stop > n)) revert InvalidQueryRange();
tokenIds = new uint256[](l);
LibMap.Uint32Map storage m = _tierTokenIds[tier];
for (uint256 i; i != l; ++i) {
Expand Down Expand Up @@ -778,7 +780,7 @@ contract SoundEditionV2_1 is ISoundEditionV2_1, ERC721AQueryableUpgradeable, ERC
* @param roles A roles bitmap.
*/
function _requireOnlyRolesOrOwner(uint256 roles) internal view {
address sender = LibMulticaller.sender();
address sender = LibMulticaller.senderOrSigner();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concerning the MulticallerWithSigner, how thorough does the review need to be? The library seems covered by the audit, so we're really just considering if we think the function usage here is appropriate. Is this correct?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The priority will be to check if the usage of senderOrSigner() here is safe, assuming that the MulticallerWithSigner is implemented perfectly.

I am 96% confident of MulticallerWithSigner.

if (!hasAnyRole(sender, roles))
if (sender != owner()) LibOps.revertUnauthorized();
}
Expand Down Expand Up @@ -910,8 +912,13 @@ contract SoundEditionV2_1 is ISoundEditionV2_1, ERC721AQueryableUpgradeable, ERC
* Reverts if there is insufficient supply.
* @param tier The tier.
* @param quantity The total number of tokens to mint.
* @return fromTokenId The first token ID minted.
* @return fromTierTokenIdIndex The first token index in the tier.
*/
function _beforeTieredMint(uint8 tier, uint256 quantity) internal returns (uint256 fromTokenId) {
function _beforeTieredMint(uint8 tier, uint256 quantity)
internal
returns (uint256 fromTokenId, uint32 fromTierTokenIdIndex)
{
unchecked {
if (quantity == 0) revert MintZeroQuantity();
fromTokenId = _nextTokenId();
Expand Down Expand Up @@ -941,6 +948,7 @@ contract SoundEditionV2_1 is ISoundEditionV2_1, ERC721AQueryableUpgradeable, ERC
m.set(minted + i, uint32(fromTokenId + i)); // Set the token IDs for the tier.
if (tier != 0) _tokenTiers.set(fromTokenId + i, tier); // Set the tier for the token ID.
}
fromTierTokenIdIndex = uint32(minted);
}
}

Expand Down
22 changes: 12 additions & 10 deletions contracts/core/interfaces/ISoundEditionV2_1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -230,21 +230,23 @@ interface ISoundEditionV2_1 is IERC721AUpgradeable, IERC2981Upgradeable {

/**
* @dev Emitted upon a mint.
* @param tier The tier.
* @param to The address to mint to.
* @param quantity The number of minted.
* @param fromTokenId The first token ID minted.
* @param tier The tier.
* @param to The address to mint to.
* @param quantity The number of minted.
* @param fromTokenId The first token ID minted.
* @param fromTierTokenIdIndex The first token index in the tier.
*/
event Minted(uint8 tier, address to, uint256 quantity, uint256 fromTokenId);
event Minted(uint8 tier, address to, uint256 quantity, uint256 fromTokenId, uint32 fromTierTokenIdIndex);

/**
* @dev Emitted upon an airdrop.
* @param tier The tier.
* @param to The recipients of the airdrop.
* @param quantity The number of tokens airdropped to each address in `to`.
* @param fromTokenId The first token ID minted to the first address in `to`.
* @param tier The tier.
* @param to The recipients of the airdrop.
* @param quantity The number of tokens airdropped to each address in `to`.
* @param fromTokenId The first token ID minted to the first address in `to`.
* @param fromTierTokenIdIndex The first token index in the tier.
*/
event Airdropped(uint8 tier, address[] to, uint256 quantity, uint256 fromTokenId);
event Airdropped(uint8 tier, address[] to, uint256 quantity, uint256 fromTokenId, uint32 fromTierTokenIdIndex);

/**
* @dev EIP-4906 event to signal marketplaces to refresh the metadata.
Expand Down
Loading
Loading