Transient Labs Stacks Protocol

The Stacks Protocol consists of sales contracts for the Transient Labs ecosystems. Sales comprise of mints, auctions, and buy nows. More can be added in the future as well.

Mints

Two contracts for minting new NFTs to ERC-721 and ERC-1155 contracts. Meant to work specifically with Transient Labs contracts but works for any contract that employs the proper function signature for externalMint (different signature for 721 vs 1155).

The mint contracts are

  • TLStacks721.sol
  • TLStacks1155.sol

Features

  • multi-tenant sales which keeps NFT contracts lighter weight with less code
  • implements a flat buyers fee in ETH per NFT minted
  • configurable for any ERC-20 token
  • velocity/marathon mint: the duration of the open edition decreases (velocity) or increases (marathon) with each mint
  • only the NFT contract owner or admins can configure/alter/cancel a mint

Auction House

A contract for reserve auctions and/or buy nows for minted ERC-721 tokens. Works for any ERC-721 token in existence.

The auction house contract is TLAuctionHouse.sol

Features

  • implements a capped percentage buyers fee
  • configurable for any ERC-20 token
  • ALWAYS respects royalties if configured on the Royalty Registry
  • Reserve auction can be configured ahead of time and have any duration desired
  • Reserve auction and buy now can be listed at the same time and if either is hit first, the other is canceled automatically
  • Only the NFT owner can configure or cancel an auction/buy now (this is true even when the NFT transfers hands outside of this contract)
  • Buy Nows can be configured ahead of time as well

Safety

  • If you have a listing on the Auction House and sell the token on another marketplace, beware that your listing on the Auction House is stale and if the NFT returns to your wallet at some point, the listing becomes valid. In the real world, this doesn't seem to occur very often, yet, you'll want to cancel your listing in this scenario.

Deployments

Contracts are deployed to the same address cross-chain using CREATE2. In doing such, constructor args have to be set to default values and then changed after deployment. Contracts are initially deployed with an EOA as the owner until initializations are made, then subsequently contract ownership is transferred to multi-sigs.

WETH Addresses

Ethereum: 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 Sepolia: 0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9 Arbitrum: 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1 Arbitrum-Sepolia: 0x980B62Da83eFf3D4576C647993b0c1D7faf17c73 Base: 0x4200000000000000000000000000000000000006 Base-Sepolia: 0x4200000000000000000000000000000000000006

Sanctions Oracle

https://go.chainalysis.com/chainalysis-oracle-docs.html

Disclaimer

While best efforts have gone into developing, testing, and peer reviewing these contracts, unexpected behavior may be present in the contracts under certain conditions. Transient Labs has a bug bounty program to preemptively squash any bugs found in our contracts.

This codebase is provided on an "as is" and "as available" basis.

We do not give any warranties and will not be liable for any loss incurred through any use of this codebase.

License

This code is copyright Transient Labs, Inc 2024 and is licensed under the MIT license.

Contents

DropPhase

Git Source

Enum to encapsulate drop phases

enum DropPhase {
    NOT_CONFIGURED,
    NOT_STARTED,
    PRESALE,
    PUBLIC_SALE,
    ENDED
}

DropType

Git Source

Enum to encapsulate drop types

enum DropType {
    NOT_CONFIGURED,
    REGULAR,
    VELOCITY
}

DropErrors

Git Source

Errors for Drops

Errors

NotDropAdmin

error NotDropAdmin();

NotApprovedMintContract

error NotApprovedMintContract();

InvalidPayoutReceiver

error InvalidPayoutReceiver();

InvalidDropSupply

error InvalidDropSupply();

DropAlreadyConfigured

error DropAlreadyConfigured();

DropUpdateNotAllowed

error DropUpdateNotAllowed();

InvalidDropType

error InvalidDropType();

NotAllowedForVelocityDrops

error NotAllowedForVelocityDrops();

MintZeroTokens

error MintZeroTokens();

NotOnAllowlist

error NotOnAllowlist();

YouShallNotMint

error YouShallNotMint();

AlreadyReachedMintAllowance

error AlreadyReachedMintAllowance();

InvalidBatchArguments

error InvalidBatchArguments();

InsufficientFunds

error InsufficientFunds();

AuctionHouseErrors

Git Source

Errors for the Auction House

Errors

PercentageTooLarge

error PercentageTooLarge();

CallerNotTokenOwner

error CallerNotTokenOwner();

AuctionHouseNotApproved

error AuctionHouseNotApproved();

PayoutToZeroAddress

error PayoutToZeroAddress();

NftNotOwnedBySeller

error NftNotOwnedBySeller();

NftNotTransferred

error NftNotTransferred();

AuctionNotConfigured

error AuctionNotConfigured();

AuctionNotStarted

error AuctionNotStarted();

AuctionStarted

error AuctionStarted();

AuctionNotOpen

error AuctionNotOpen();

BidTooLow

error BidTooLow();

AuctionEnded

error AuctionEnded();

AuctionNotEnded

error AuctionNotEnded();

InsufficientMsgValue

error InsufficientMsgValue();

SaleNotConfigured

error SaleNotConfigured();

SaleNotOpen

error SaleNotOpen();

Auction

Git Source

Auction struct

struct Auction {
    address seller;
    address payoutReceiver;
    address currencyAddress;
    address highestBidder;
    uint256 highestBid;
    uint256 reservePrice;
    uint256 auctionOpenTime;
    uint256 startTime;
    uint256 duration;
}

Sale

Git Source

Sale struct

struct Sale {
    address seller;
    address payoutReceiver;
    address currencyAddress;
    uint256 price;
    uint256 saleOpenTime;
}

ITLAuctionHouseEvents

Git Source

Events

RoyaltyEngineUpdated

event RoyaltyEngineUpdated(address indexed prevRoyaltyEngine, address indexed newRoyaltyEngine);

WethUpdated

event WethUpdated(address indexed prevWeth, address indexed newWeth);

MinBidIncreaseUpdated

event MinBidIncreaseUpdated(uint256 indexed newMinBidIncreasePerc, uint256 indexed newMinBidIncreaseLimit);

ProtocolFeeUpdated

event ProtocolFeeUpdated(
    address indexed newProtocolFeeReceiver, uint256 indexed newProtocolFeePerc, uint256 indexed newProtocolFeeLimit
);

AuctionConfigured

event AuctionConfigured(address indexed sender, address indexed nftAddress, uint256 indexed tokenId, Auction auction);

AuctionCanceled

event AuctionCanceled(address indexed sender, address indexed nftAddress, uint256 indexed tokenId);

AuctionSettled

event AuctionSettled(address indexed sender, address indexed nftAddress, uint256 indexed tokenId, Auction auction);

AuctionBid

event AuctionBid(address indexed sender, address indexed nftAddress, uint256 indexed tokenId, Auction auction);

SaleConfigured

event SaleConfigured(address indexed sender, address indexed nftAddress, uint256 indexed tokenId, Sale sale);

SaleCanceled

event SaleCanceled(address indexed sender, address indexed nftAddress, uint256 indexed tokenId);

SaleFulfilled

event SaleFulfilled(address indexed sender, address indexed nftAddress, uint256 indexed tokenId, Sale sale);

Drop

Git Source

stacks drop struct

struct Drop {
    DropType dropType;
    address payoutReceiver;
    uint256 initialSupply;
    uint256 supply;
    uint256 allowance;
    address currencyAddress;
    uint256 startTime;
    uint256 presaleDuration;
    uint256 presaleCost;
    bytes32 presaleMerkleRoot;
    uint256 publicDuration;
    uint256 publicCost;
    int256 decayRate;
}

ITLStacks1155Events

Git Source

Events

WethUpdated

event WethUpdated(address indexed prevWeth, address indexed newWeth);

ProtocolFeeUpdated

event ProtocolFeeUpdated(address indexed newProtocolFeeReceiver, uint256 indexed newProtocolFee);

DropConfigured

event DropConfigured(address indexed nftAddress, uint256 indexed tokenId, Drop drop);

DropUpdated

event DropUpdated(address indexed nftAddress, uint256 indexed tokenId, Drop drop);

DropClosed

event DropClosed(address indexed nftAddress, uint256 indexed tokenId);

Purchase

event Purchase(
    address indexed nftAddress,
    uint256 indexed tokenId,
    address nftReceiver,
    address currencyAddress,
    uint256 amount,
    uint256 price,
    int256 decayRate,
    bool isPresale
);

Drop

Git Source

stacks drop struct

struct Drop {
    DropType dropType;
    address payoutReceiver;
    uint256 initialSupply;
    uint256 supply;
    uint256 allowance;
    address currencyAddress;
    uint256 startTime;
    uint256 presaleDuration;
    uint256 presaleCost;
    bytes32 presaleMerkleRoot;
    uint256 publicDuration;
    uint256 publicCost;
    int256 decayRate;
    string baseUri;
}

ITLStacks721Events

Git Source

Events

WethUpdated

event WethUpdated(address indexed prevWeth, address indexed newWeth);

ProtocolFeeUpdated

event ProtocolFeeUpdated(address indexed newProtocolFeeReceiver, uint256 indexed newProtocolFee);

DropConfigured

event DropConfigured(address indexed nftAddress, Drop drop);

DropUpdated

event DropUpdated(address indexed nftAddress, Drop drop);

DropClosed

event DropClosed(address indexed nftAddress);

Purchase

event Purchase(
    address indexed nftAddress,
    address nftReceiver,
    address currencyAddress,
    uint256 amount,
    uint256 price,
    int256 decayRate,
    bool isPresale
);

TLAuctionHouse

Git Source

Inherits: Ownable, Pausable, ReentrancyGuard, RoyaltyPayoutHelper, ITLAuctionHouseEvents, AuctionHouseErrors

Author: transientlabs.xyz

Transient Labs Auction House with Reserve Auctions and Buy Now Sales for ERC-721 tokens

State Variables

VERSION

string public constant VERSION = "2.3.0";

EXTENSION_TIME

uint256 public constant EXTENSION_TIME = 15 minutes;

BASIS

uint256 public constant BASIS = 10_000;

protocolFeeReceiver

address public protocolFeeReceiver;

minBidIncreasePerc

uint256 public minBidIncreasePerc;

minBidIncreaseLimit

uint256 public minBidIncreaseLimit;

protocolFeePerc

uint256 public protocolFeePerc;

protocolFeeLimit

uint256 public protocolFeeLimit;

_auctions

mapping(address => mapping(uint256 => Auction)) internal _auctions;

_sales

mapping(address => mapping(uint256 => Sale)) internal _sales;

Functions

constructor

constructor(
    address initOwner,
    address initSanctionsOracle,
    address initWethAddress,
    address initRoyaltyEngineAddress,
    address initProtocolFeeReceiver,
    uint256 initMinBidIncreasePerc,
    uint256 initMinBidIncreaseLimit,
    uint256 initProtocolFeePerc,
    uint256 initProtocolFeeLimit
)
    Ownable(initOwner)
    Pausable
    ReentrancyGuard
    RoyaltyPayoutHelper(initSanctionsOracle, initWethAddress, initRoyaltyEngineAddress);

setRoyaltyEngine

Function to set a new royalty engine address

Requires owner

function setRoyaltyEngine(address newRoyaltyEngine) external onlyOwner;

Parameters

NameTypeDescription
newRoyaltyEngineaddressThe new royalty engine address

setWethAddress

Function to set a new weth address

Requires owner

function setWethAddress(address newWethAddress) external onlyOwner;

Parameters

NameTypeDescription
newWethAddressaddressThe new weth address

setMinBidIncreaseSettings

Function to set the min bid increase settings

Requires owner

function setMinBidIncreaseSettings(uint256 newMinBidIncreasePerc, uint256 newMinBidIncreaseLimit) external onlyOwner;

Parameters

NameTypeDescription
newMinBidIncreasePercuint256The new minimum bid increase nominal percentage, out of BASIS
newMinBidIncreaseLimituint256The new minimum bid increase absolute limit

setProtocolFeeSettings

Function to set the protocol fee settings

Requires owner

function setProtocolFeeSettings(address newProtocolFeeReceiver, uint256 newProtocolFeePerc, uint256 newProtocolFeeLimit)
    external
    onlyOwner;

Parameters

NameTypeDescription
newProtocolFeeReceiveraddressThe new protocol fee receiver
newProtocolFeePercuint256The new protocol fee percentage, out of BASIS
newProtocolFeeLimituint256The new protocol fee limit

pause

Function to pause the contract

Requires owner

function pause(bool status) external onlyOwner;

Parameters

NameTypeDescription
statusboolThe boolean to set the internal pause variable

setSanctionsOracle

Function to set the sanctions oracle

Requires owner

function setSanctionsOracle(address newOracle) external onlyOwner;

Parameters

NameTypeDescription
newOracleaddressThe new oracle address

configureAuction

Function to configure an auction

*Requires the following items to be true

  • contract is not paused
  • the auction hasn't been configured yet for the current token owner
  • msg.sender is the owner of the token
  • auction house is approved for all
  • payoutReceiver isn't the zero address*
function configureAuction(
    address nftAddress,
    uint256 tokenId,
    address payoutReceiver,
    address currencyAddress,
    uint256 reservePrice,
    uint256 auctionOpenTime,
    uint256 duration,
    bool reserveAuction
) external whenNotPaused nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The nft token id
payoutReceiveraddressThe address that receives the payout from the auction
currencyAddressaddressThe currency to use
reservePriceuint256The auction reserve price
auctionOpenTimeuint256The time at which bidding is allowed
durationuint256The duration of the auction after it is started
reserveAuctionboolA flag dictating if the auction is a reserve auction or regular scheduled auction

cancelAuction

Function to cancel an auction

*Requires the following to be true

  • msg.sender to be the auction seller
  • the auction cannot be started*
function cancelAuction(address nftAddress, uint256 tokenId) external nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The nft token id

bid

Function to bid on an auction

*Requires the following to be true

  • contract is not paused
  • block.timestamp is greater than the auction open timestamp
  • bid meets or exceeds the reserve price / min bid price
  • msg.sender has attached enough eth/erc20 as specified by amount
  • protocol fee has been supplied, if needed*
function bid(address nftAddress, uint256 tokenId, uint256 amount) external payable whenNotPaused nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The nft token id
amountuint256The amount to bid in the currency address set in the auction

settleAuction

Function to settle an auction

Can be called by anyone

*Requires the following to be true

  • auction has been started
  • auction has ended*
function settleAuction(address nftAddress, uint256 tokenId) external nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The nft token id

configureSale

Function to configure a buy now sale

*Requires the following to be true

  • contract is not paused
  • the sale hasn't been configured yet by the current token owner
  • an auction hasn't been started - this is captured by token ownership
  • msg.sender is the owner of the token
  • auction house is approved for all
  • payoutReceiver isn't the zero address*
function configureSale(
    address nftAddress,
    uint256 tokenId,
    address payoutReceiver,
    address currencyAddress,
    uint256 price,
    uint256 saleOpenTime
) external whenNotPaused nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The nft token id
payoutReceiveraddressThe address that receives the payout from the sale
currencyAddressaddressThe currency to use
priceuint256The sale price
saleOpenTimeuint256The time at which the sale opens

cancelSale

Function to cancel a sale

Requires msg.sender to be the token owner

function cancelSale(address nftAddress, uint256 tokenId) external nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The nft token id

buyNow

Function to buy a token

*Requires the following to be true

  • contract is not paused
  • block.timestamp is greater than the sale open timestamp
  • msg.sender has attached enough eth/erc20 as specified by the sale
  • protocol fee has been supplied, if needed*
function buyNow(address nftAddress, uint256 tokenId) external payable whenNotPaused nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The nft token id

getSale

function to get a sale

function getSale(address nftAddress, uint256 tokenId) external view returns (Sale memory);

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The nft token id

Returns

NameTypeDescription
<none>Salesale The sale struct

getAuction

function to get an auction

function getAuction(address nftAddress, uint256 tokenId) external view returns (Auction memory);

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The nft token id

Returns

NameTypeDescription
<none>Auctionauction The auction struct

calcNextMinBid

function to get the next minimum bid price for an auction

function calcNextMinBid(address nftAddress, uint256 tokenId) external view returns (uint256);

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The nft token id

Returns

NameTypeDescription
<none>uint256uint256 The next minimum bid required

calcProtocolFee

function to calculate the protocol fee

function calcProtocolFee(uint256 amount) external view returns (uint256);

Parameters

NameTypeDescription
amountuint256The value to calculate the fee for

Returns

NameTypeDescription
<none>uint256uint256 The calculated fee

_setMinBidIncreaseSettings

Internal function to set the min bid increase settings

function _setMinBidIncreaseSettings(uint256 newMinBidIncreasePerc, uint256 newMinBidIncreaseLimit) internal;

Parameters

NameTypeDescription
newMinBidIncreasePercuint256The new minimum bid increase nominal percentage, out of BASIS
newMinBidIncreaseLimituint256The new minimum bid increase absolute limit

_setProtocolFeeSettings

Internal function to set the protocol fee settings

function _setProtocolFeeSettings(
    address newProtocolFeeReceiver,
    uint256 newProtocolFeePerc,
    uint256 newProtocolFeeLimit
) internal;

Parameters

NameTypeDescription
newProtocolFeeReceiveraddressThe new protocol fee receiver
newProtocolFeePercuint256The new protocol fee percentage, out of BASIS
newProtocolFeeLimituint256The new protocol fee limit

_checkTokenOwnership

Internal function to check if a token is owned by an address

function _checkTokenOwnership(IERC721 nft, uint256 tokenId, address potentialTokenOwner) internal view returns (bool);

Parameters

NameTypeDescription
nftIERC721The nft contract
tokenIduint256The nft token id
potentialTokenOwneraddressThe potential token owner to check against

Returns

NameTypeDescription
<none>boolbool Indication of if the address in quesion is the owner of the token

_checkAuctionHouseApproval

Internal function to check if the auction house is approved for all

function _checkAuctionHouseApproval(IERC721 nft, address seller) internal view returns (bool);

Parameters

NameTypeDescription
nftIERC721The nft contract
selleraddressThe seller to check against

Returns

NameTypeDescription
<none>boolbool Indication of if the auction house is approved for all by the seller

_checkPayoutReceiver

Internal function to check if a payout address is a valid address

function _checkPayoutReceiver(address payoutReceiver) internal pure returns (bool);

Parameters

NameTypeDescription
payoutReceiveraddressThe payout address to check

Returns

NameTypeDescription
<none>boolbool Indication of if the payout address is not the zero address

_calcNextMinBid

Internal function to calculate the next min bid price

function _calcNextMinBid(uint256 currentBid) internal view returns (uint256 nextMinBid);

Parameters

NameTypeDescription
currentBiduint256The current bid

Returns

NameTypeDescription
nextMinBiduint256The next minimum bid

_calcProtocolFee

Internal function to calculate the protocol fee

function _calcProtocolFee(uint256 amount) internal view returns (uint256 fee);

Parameters

NameTypeDescription
amountuint256The value of the sale

Returns

NameTypeDescription
feeuint256The protocol fee

_payout

Internal function to payout from the contract

function _payout(address nftAddress, uint256 tokenId, address currencyAddress, uint256 amount, address payoutReceiver)
    internal;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The token id
currencyAddressaddressThe currency address (ZERO ADDRESS == ETH)
amountuint256The sale/auction end price
payoutReceiveraddressThe receiver for the sale payout (what's remaining after royalties)

TLStacks1155

Git Source

Inherits: Ownable, Pausable, ReentrancyGuard, TransferHelper, SanctionsCompliance, ITLStacks1155Events, DropErrors

Author: transientlabs.xyz

Transient Labs Stacks mint contract for ERC1155TL contracts

State Variables

VERSION

string public constant VERSION = "2.3.1";

ADMIN_ROLE

bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");

APPROVED_MINT_CONTRACT

bytes32 public constant APPROVED_MINT_CONTRACT = keccak256("APPROVED_MINT_CONTRACT");

protocolFeeReceiver

address public protocolFeeReceiver;

protocolFee

uint256 public protocolFee;

weth

address public weth;

_drops

mapping(address => mapping(uint256 => Drop)) internal _drops;

_numberMinted

mapping(address => mapping(uint256 => mapping(uint256 => mapping(address => uint256)))) internal _numberMinted;

_rounds

mapping(address => mapping(uint256 => uint256)) internal _rounds;

Functions

constructor

constructor(
    address initOwner,
    address initSanctionsOracle,
    address initWethAddress,
    address initProtocolFeeReceiver,
    uint256 initProtocolFee
) Ownable(initOwner) Pausable ReentrancyGuard SanctionsCompliance(initSanctionsOracle);

setWethAddress

Function to set a new weth address

Requires owner

function setWethAddress(address newWethAddress) external onlyOwner;

Parameters

NameTypeDescription
newWethAddressaddressThe new weth address

setProtocolFeeSettings

Function to set the protocol fee settings

Requires owner

function setProtocolFeeSettings(address newProtocolFeeReceiver, uint256 newProtocolFee) external onlyOwner;

Parameters

NameTypeDescription
newProtocolFeeReceiveraddressThe new protocol fee receiver
newProtocolFeeuint256The new protocol fee in ETH

pause

Function to pause the contract

Requires owner

function pause(bool status) external onlyOwner;

Parameters

NameTypeDescription
statusboolThe boolean to set the internal pause variable

setSanctionsOracle

Function to set the sanctions oracle

Requires owner

function setSanctionsOracle(address newOracle) external onlyOwner;

Parameters

NameTypeDescription
newOracleaddressThe new oracle address

configureDrop

Function to configure a drop

Caller must be the nft contract owner or an admin on the contract

*Reverts if

  • the payout receiver is the zero address
  • a drop is already configured and live
  • the intiialSupply does not equal the supply
  • the decayRate is non-zero and there is a presale configured*
function configureDrop(address nftAddress, uint256 tokenId, Drop calldata drop) external whenNotPaused nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The token id of the ERC-1155 token
dropDropThe drop to configure

updateDropPayoutReceiver

Function to update the payout receiver of a drop

Caller must be the nft contract owner or an admin on the contract

function updateDropPayoutReceiver(address nftAddress, uint256 tokenId, address payoutReceiver)
    external
    whenNotPaused
    nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The token id of the ERC-1155 token
payoutReceiveraddressThe recipient of the funds from the mint

updateDropAllowance

Function to update the drop public allowance

Caller must be the nft contract owner or an admin on the contract

function updateDropAllowance(address nftAddress, uint256 tokenId, uint256 allowance)
    external
    whenNotPaused
    nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The token id of the ERC-1155 token
allowanceuint256The number of tokens allowed to be minted per wallet during the public phase of the drop

updateDropPrices

Function to update the drop prices and currency

Caller must be the nft contract owner or an admin on the contract

function updateDropPrices(
    address nftAddress,
    uint256 tokenId,
    address currencyAddress,
    uint256 presaleCost,
    uint256 publicCost
) external whenNotPaused nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The token id of the ERC-1155 token
currencyAddressaddressThe currency address (zero address represents ETH)
presaleCostuint256The cost of each token during the presale phase
publicCostuint256The cost of each token during the presale phase

updateDropDuration

Function to adjust drop durations

Caller must be the nft contract owner or an admin on the contract

function updateDropDuration(
    address nftAddress,
    uint256 tokenId,
    uint256 startTime,
    uint256 presaleDuration,
    uint256 publicDuration
) external whenNotPaused nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The token id of the ERC-1155 token
startTimeuint256The timestamp at which the drop starts
presaleDurationuint256The duration of the presale phase of the drop, in seconds
publicDurationuint256The duration of the public phase

updateDropPresaleMerkleRoot

Function to adjust the drop merkle root

Caller must be the nft contract owner or an admin on the contract

function updateDropPresaleMerkleRoot(address nftAddress, uint256 tokenId, bytes32 presaleMerkleRoot)
    external
    whenNotPaused
    nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The token id of the ERC-1155 token
presaleMerkleRootbytes32The merkle root for the presale phase (each leaf is abi encoded with the recipient and number they can mint during presale)

updateDropDecayRate

Function to adjust the drop decay rate

Caller must be the nft contract owner or an admin on the contract

function updateDropDecayRate(address nftAddress, uint256 tokenId, int256 decayRate)
    external
    whenNotPaused
    nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The token id of the ERC-1155 token
decayRateint256The merkle root for the presale phase (each leaf is abi encoded with the recipient and number they can mint during presale)

closeDrop

function closeDrop(address nftAddress, uint256 tokenId) external nonReentrant;

purchase

Function to purchase a single token via a drop

*Reverts on any of the following conditions

  • Drop isn't active or configured
  • numberToMint is 0
  • Invalid merkle proof during the presale phase
  • Insufficent protocol fee
  • Insufficient funds
  • Already minted the allowance for the recipient
  • Receiver is a contract that doesn't implement proper ERC-1155 receiving functions*
function purchase(
    address nftAddress,
    uint256 tokenId,
    address recipient,
    uint256 numberToMint,
    uint256 presaleNumberCanMint,
    bytes32[] calldata proof
) external payable whenNotPaused nonReentrant returns (uint256 refundAmount);

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The nft token id
recipientaddressThe receiver of the nft (msg.sender is the payer but this allows delegation)
numberToMintuint256The number of tokens to mint
presaleNumberCanMintuint256The number of tokens the recipient can mint during presale
proofbytes32[]The merkle proof for the presale page

Returns

NameTypeDescription
refundAmountuint256The amount of eth refunded bqck to the caller

getDrop

Function to get a drop

function getDrop(address nftAddress, uint256 tokenId) external view returns (Drop memory);

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The nft token id

Returns

NameTypeDescription
<none>DropDrop The drop for the nft contract and token id

getDrops

Function to get a number of drops for a contract

function getDrops(address nftAddress, uint256[] calldata tokenIds) external view returns (Drop[] memory drops);

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIdsuint256[]The nft token ids

Returns

NameTypeDescription
dropsDrop[]An array of Drops

getNumberMinted

Function to get number minted on a drop for an address

function getNumberMinted(address nftAddress, uint256 tokenId, address recipient) external view returns (uint256);

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The nft token id
recipientaddressThe recipient of the nft

Returns

NameTypeDescription
<none>uint256uint256 The number of tokens minted

getDropPhase

Function to get the drop phase

function getDropPhase(address nftAddress, uint256 tokenId) external view returns (DropPhase);

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The nft token id

Returns

NameTypeDescription
<none>DropPhaseDropPhase The drop phase

getDropRound

Function to get the drop round

function getDropRound(address nftAddress, uint256 tokenId) external view returns (uint256);

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The nft token id

Returns

NameTypeDescription
<none>uint256uint256 The round for the drop based on the nft contract and token id

_setWethAddress

Internal function to set the weth address

function _setWethAddress(address newWethAddress) internal;

Parameters

NameTypeDescription
newWethAddressaddressThe new weth address

_setProtocolFeeSettings

Internal function to set the protocol fee settings

function _setProtocolFeeSettings(address newProtocolFeeReceiver, uint256 newProtocolFee) internal;

Parameters

NameTypeDescription
newProtocolFeeReceiveraddressThe new protocol fee receiver
newProtocolFeeuint256The new protocol fee in ETH

_isDropAdmin

Internal function to check if msg.sender is the owner or an admin on the contract

function _isDropAdmin(address nftAddress) internal view returns (bool);

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address

Returns

NameTypeDescription
<none>boolbool Boolean indicating if msg.sender is the owner or an admin on the nft contract

_isApprovedMintContract

Intenral function to check if this contract is an approved mint contract

function _isApprovedMintContract(address nftAddress) internal view returns (bool);

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address

Returns

NameTypeDescription
<none>boolbool Boolean indicating if this contract is approved or not

_checkPayoutReceiver

Internal function to check if a payout address is a valid address

function _checkPayoutReceiver(address payoutReceiver) internal pure returns (bool);

Parameters

NameTypeDescription
payoutReceiveraddressThe payout address to check

Returns

NameTypeDescription
<none>boolbool Indication of if the payout address is not the zero address

_getDropPhase

Internal function to get the drop phase

function _getDropPhase(Drop memory drop) internal view returns (DropPhase);

Parameters

NameTypeDescription
dropDropThe drop in question

Returns

NameTypeDescription
<none>DropPhaseDropPhase The drop phase enum value

_getNumberCanMint

Internal function to determine how many tokens can be minted by an address

function _getNumberCanMint(uint256 allowance, uint256 numberMinted, uint256 supply)
    internal
    pure
    returns (uint256 numberCanMint);

Parameters

NameTypeDescription
allowanceuint256The amount allowed to mint
numberMinteduint256The amount already minted
supplyuint256The drop supply

Returns

NameTypeDescription
numberCanMintuint256The number of tokens allowed to mint

_updateDropState

Function to update the state of the drop

function _updateDropState(
    address nftAddress,
    uint256 tokenId,
    uint256 round,
    address recipient,
    uint256 numberToMint,
    Drop memory drop
) internal;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The nft token id
rounduint256The drop round for number minted
recipientaddressThe receiver of the nft (msg.sender is the payer but this allows delegation)
numberToMintuint256The number of tokens to mint
dropDropThe Drop cached in memory

_settleUp

Internal function to distribute funds for a _purchase

function _settleUp(uint256 numberToMint, uint256 cost, Drop memory drop) internal returns (uint256 refundAmount);

Parameters

NameTypeDescription
numberToMintuint256The number of tokens that can be minted
costuint256The cost per token
dropDropThe drop

Returns

NameTypeDescription
refundAmountuint256The amount of eth refunded to msg.sender

_mintToken

Internal function to mint the token

function _mintToken(address nftAddress, uint256 tokenId, address recipient, uint256 numberToMint) internal;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
tokenIduint256The nft token id
recipientaddressThe receiver of the nft (msg.sender is the payer but this allows delegation)
numberToMintuint256The number of tokens to mint

TLStacks721

Git Source

Inherits: Ownable, Pausable, ReentrancyGuard, TransferHelper, SanctionsCompliance, ITLStacks721Events, DropErrors

Author: transientlabs.xyz

Transient Labs Stacks mint contract for ERC721TL-based contracts

State Variables

VERSION

string public constant VERSION = "2.3.1";

ADMIN_ROLE

bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");

APPROVED_MINT_CONTRACT

bytes32 public constant APPROVED_MINT_CONTRACT = keccak256("APPROVED_MINT_CONTRACT");

protocolFeeReceiver

address public protocolFeeReceiver;

protocolFee

uint256 public protocolFee;

weth

address public weth;

_drops

mapping(address => Drop) internal _drops;

_numberMinted

mapping(address => mapping(uint256 => mapping(address => uint256))) internal _numberMinted;

_rounds

mapping(address => uint256) internal _rounds;

Functions

constructor

constructor(
    address initOwner,
    address initSanctionsOracle,
    address initWethAddress,
    address initProtocolFeeReceiver,
    uint256 initProtocolFee
) Ownable(initOwner) Pausable ReentrancyGuard SanctionsCompliance(initSanctionsOracle);

setWethAddress

Function to set a new weth address

Requires owner

function setWethAddress(address newWethAddress) external onlyOwner;

Parameters

NameTypeDescription
newWethAddressaddressThe new weth address

setProtocolFeeSettings

Function to set the protocol fee settings

Requires owner

function setProtocolFeeSettings(address newProtocolFeeReceiver, uint256 newProtocolFee) external onlyOwner;

Parameters

NameTypeDescription
newProtocolFeeReceiveraddressThe new protocol fee receiver
newProtocolFeeuint256The new protocol fee in ETH

pause

Function to pause the contract

Requires owner

function pause(bool status) external onlyOwner;

Parameters

NameTypeDescription
statusboolThe boolean to set the internal pause variable

setSanctionsOracle

Function to set the sanctions oracle

Requires owner

function setSanctionsOracle(address newOracle) external onlyOwner;

Parameters

NameTypeDescription
newOracleaddressThe new oracle address

configureDrop

Function to configure a drop

Caller must be the nft contract owner or an admin on the contract

*Reverts if

  • the payout receiver is the zero address
  • a drop is already configured and live
  • the intialSupply does not equal the supply
  • the decayRate is non-zero and there is a presale configured*
function configureDrop(address nftAddress, Drop calldata drop) external whenNotPaused nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
dropDropThe drop to configure

updateDropPayoutReceiver

Function to update the payout receiver of a drop

Caller must be the nft contract owner or an admin on the contract

function updateDropPayoutReceiver(address nftAddress, address payoutReceiver) external whenNotPaused nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
payoutReceiveraddressThe recipient of the funds from the mint

updateDropAllowance

Function to update the drop public allowance

Caller must be the nft contract owner or an admin on the contract

function updateDropAllowance(address nftAddress, uint256 allowance) external whenNotPaused nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
allowanceuint256The number of tokens allowed to be minted per wallet during the public phase of the drop

updateDropPrices

Function to update the drop prices and currency

Caller must be the nft contract owner or an admin on the contract

function updateDropPrices(address nftAddress, address currencyAddress, uint256 presaleCost, uint256 publicCost)
    external
    whenNotPaused
    nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
currencyAddressaddressThe currency address (zero address represents ETH)
presaleCostuint256The cost of each token during the presale phase
publicCostuint256The cost of each token during the presale phase

updateDropDuration

Function to adjust drop durations

Caller must be the nft contract owner or an admin on the contract

function updateDropDuration(address nftAddress, uint256 startTime, uint256 presaleDuration, uint256 publicDuration)
    external
    whenNotPaused
    nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
startTimeuint256The timestamp at which the drop starts
presaleDurationuint256The duration of the presale phase of the drop, in seconds
publicDurationuint256The duration of the public phase

updateDropPresaleMerkleRoot

Function to alter a drop merkle root

Caller must be the nft contract owner or an admin on the contract

function updateDropPresaleMerkleRoot(address nftAddress, bytes32 presaleMerkleRoot)
    external
    whenNotPaused
    nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
presaleMerkleRootbytes32The merkle root for the presale phase (each leaf is abi encoded with the recipient and number they can mint during presale)

updateDropDecayRate

Function to adjust the drop decay rate

Caller must be the nft contract owner or an admin on the contract

function updateDropDecayRate(address nftAddress, int256 decayRate) external whenNotPaused nonReentrant;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
decayRateint256The merkle root for the presale phase (each leaf is abi encoded with the recipient and number they can mint during presale)

closeDrop

function closeDrop(address nftAddress) external nonReentrant;

purchase

Function to purchase tokens on a drop

*Reverts on any of the following conditions

  • Drop isn't active or configured
  • numberToMint is 0
  • Invalid merkle proof during the presale phase
  • Insufficent protocol fee
  • Insufficient funds
  • Already minted the allowance for the recipient*
function purchase(
    address nftAddress,
    address recipient,
    uint256 numberToMint,
    uint256 presaleNumberCanMint,
    bytes32[] calldata proof
) external payable whenNotPaused nonReentrant returns (uint256 refundAmount);

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
recipientaddressThe receiver of the nft (msg.sender is the payer but this allows delegation)
numberToMintuint256The number of tokens to mint
presaleNumberCanMintuint256The number of tokens the recipient can mint during presale
proofbytes32[]The merkle proof for the presale page

Returns

NameTypeDescription
refundAmountuint256The amount of eth refunded to the caller

getDrop

Function to get a drop

function getDrop(address nftAddress) external view returns (Drop memory);

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address

Returns

NameTypeDescription
<none>DropDrop The drop for the nft contract and token id

getNumberMinted

Function to get number minted on a drop for an address

function getNumberMinted(address nftAddress, address recipient) external view returns (uint256);

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
recipientaddressThe recipient of the nft

Returns

NameTypeDescription
<none>uint256uint256 The number of tokens minted

getDropPhase

Function to get the drop phase

function getDropPhase(address nftAddress) external view returns (DropPhase);

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address

Returns

NameTypeDescription
<none>DropPhaseDropPhase The drop phase

getDropRound

Function to get the drop round

function getDropRound(address nftAddress) external view returns (uint256);

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address

Returns

NameTypeDescription
<none>uint256uint256 The round for the drop based on the nft contract and token id

_setWethAddress

Internal function to set the weth address

function _setWethAddress(address newWethAddress) internal;

Parameters

NameTypeDescription
newWethAddressaddressThe new weth address

_setProtocolFeeSettings

Internal function to set the protocol fee settings

function _setProtocolFeeSettings(address newProtocolFeeReceiver, uint256 newProtocolFee) internal;

Parameters

NameTypeDescription
newProtocolFeeReceiveraddressThe new protocol fee receiver
newProtocolFeeuint256The new protocol fee in ETH

_isDropAdmin

Internal function to check if msg.sender is the owner or an admin on the contract

function _isDropAdmin(address nftAddress) internal view returns (bool);

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address

Returns

NameTypeDescription
<none>boolbool Boolean indicating if msg.sender is the owner or an admin on the nft contract

_isApprovedMintContract

Intenral function to check if this contract is an approved mint contract

function _isApprovedMintContract(address nftAddress) internal view returns (bool);

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address

Returns

NameTypeDescription
<none>boolbool Boolean indicating if this contract is approved or not

_checkPayoutReceiver

Internal function to check if a payout address is a valid address

function _checkPayoutReceiver(address payoutReceiver) internal pure returns (bool);

Parameters

NameTypeDescription
payoutReceiveraddressThe payout address to check

Returns

NameTypeDescription
<none>boolbool Indication of if the payout address is not the zero address

_getDropPhase

Internal function to get the drop phase

function _getDropPhase(Drop memory drop) internal view returns (DropPhase);

Parameters

NameTypeDescription
dropDropThe drop in question

Returns

NameTypeDescription
<none>DropPhaseDropPhase The drop phase enum value

_getNumberCanMint

Internal function to determine how many tokens can be minted by an address

function _getNumberCanMint(uint256 allowance, uint256 numberMinted, uint256 supply)
    internal
    pure
    returns (uint256 numberCanMint);

Parameters

NameTypeDescription
allowanceuint256The amount allowed to mint
numberMinteduint256The amount already minted
supplyuint256The drop supply

Returns

NameTypeDescription
numberCanMintuint256The number of tokens allowed to mint

_updateDropState

Function to update the state of the drop

function _updateDropState(address nftAddress, uint256 round, address recipient, uint256 numberToMint, Drop memory drop)
    internal;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
rounduint256The drop round for number minted
recipientaddressThe receiver of the nft (msg.sender is the payer but this allows delegation)
numberToMintuint256The number of tokens to mint
dropDropThe Drop cached in memory

_settleUp

Internal function to distribute funds for a _purchase

function _settleUp(uint256 numberToMint, uint256 cost, Drop memory drop) internal returns (uint256 refundAmount);

Parameters

NameTypeDescription
numberToMintuint256The number of tokens that can be minted
costuint256The cost per token
dropDropThe drop

Returns

NameTypeDescription
refundAmountuint256The amount of eth refunded to msg.sender

_mintToken

Internal function to mint the token

function _mintToken(address nftAddress, address recipient, uint256 numberToMint, Drop memory drop) internal;

Parameters

NameTypeDescription
nftAddressaddressThe nft contract address
recipientaddressThe receiver of the nft (msg.sender is the payer but this allows delegation)
numberToMintuint256The number of tokens to mint
dropDropThe drop cached in memory (not read from storage again)