Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

TokenPurchasable

Git Source

Inherits: PausableUpgradeable, ReentrancyGuardTransientUpgradeable

Author: EVMAuth

Enables token purchases with native and ERC-20 currency support.

Abstract contract implementing multi-currency purchasing with reentrancy protection. Each token type can be configured with independent pricing in native currency and/or multiple ERC-20 tokens. Uses EIP-7201 storage pattern for upgrade safety.

State Variables

TokenPurchasableStorageLocation

EIP-7201 storage slot for TokenPurchasable state.

Computed as: keccak256(abi.encode(uint256(keccak256("tokenpurchasable.storage.TokenPurchasable")) - 1)). & ~bytes32(uint256(0xff)). Prevents storage collisions in upgradeable contracts.

bytes32 private constant TokenPurchasableStorageLocation =
    0x54c84cf2875b53587e3bd1a41cdb4ae126fe9184d0b1bd9183d4f9005d2ff600;

Functions

_getTokenPurchasableStorage

Retrieves the storage struct for TokenPurchasable.

Internal function using inline assembly for direct storage access.

function _getTokenPurchasableStorage() private pure returns (TokenPurchasableStorage storage $);

Returns

NameTypeDescription
$TokenPurchasableStorageStorage pointer to TokenPurchasableStorage struct

__TokenPurchasable_init

Internal initializer for TokenPurchasable setup.

Sets initial treasury address.

function __TokenPurchasable_init(address payable initialTreasury) internal onlyInitializing;

Parameters

NameTypeDescription
initialTreasuryaddress payableAddress to receive purchase revenues

__TokenPurchasable_init_unchained

Unchained initializer for contract-specific storage.

Validates and sets treasury address.

function __TokenPurchasable_init_unchained(address payable initialTreasury) internal onlyInitializing;

Parameters

NameTypeDescription
initialTreasuryaddress payableAddress to receive purchase revenues

tokenPrice

Gets native currency price for a token type.

Reverts if price is 0 (not for sale)

Note: throws: TokenNotForSaleWithNativeCurrency When price is 0

function tokenPrice(uint256 id) public view virtual returns (uint256 price);

Parameters

NameTypeDescription
iduint256Token type identifier

Returns

NameTypeDescription
priceuint256Native currency price

tokenERC20Prices

Gets all accepted ERC-20 payment options.

Returns array of payment tokens and their prices.

function tokenERC20Prices(uint256 id) public view virtual returns (PaymentToken[] memory prices);

Parameters

NameTypeDescription
iduint256Token type identifier

Returns

NameTypeDescription
pricesPaymentToken[]Array of PaymentToken structs

treasury

Gets current treasury address.

All purchase revenues are sent to this address.

function treasury() public view virtual returns (address);

Returns

NameTypeDescription
<none>addressTreasury address

purchase

Purchase tokens for caller using native currency.

Requires exact or excess payment. Excess is refunded.

Note: emits: TokenPurchased

function purchase(uint256 id, uint256 amount) external payable virtual whenNotPaused nonReentrant;

Parameters

NameTypeDescription
iduint256Token type identifier to purchase
amountuint256Quantity to purchase

purchaseFor

Purchase tokens for specified recipient using native currency.

Caller pays, receiver gets tokens. Excess payment refunded to caller.

function purchaseFor(address receiver, uint256 id, uint256 amount)
    external
    payable
    virtual
    whenNotPaused
    nonReentrant;

Parameters

NameTypeDescription
receiveraddressAddress to receive purchased tokens
iduint256Token type identifier to purchase
amountuint256Quantity to purchase

purchaseWithERC20

Purchase tokens for caller using ERC-20 payment.

Requires sufficient balance and approval.

function purchaseWithERC20(address paymentToken, uint256 id, uint256 amount)
    external
    virtual
    whenNotPaused
    nonReentrant;

Parameters

NameTypeDescription
paymentTokenaddressERC-20 contract address for payment
iduint256Token type identifier to purchase
amountuint256Quantity to purchase

purchaseWithERC20For

Purchase tokens for specified recipient using ERC-20 payment.

Caller pays with ERC-20, receiver gets tokens.

function purchaseWithERC20For(address receiver, address paymentToken, uint256 id, uint256 amount)
    external
    virtual
    whenNotPaused
    nonReentrant;

Parameters

NameTypeDescription
receiveraddressAddress to receive purchased tokens
paymentTokenaddressERC-20 contract address for payment
iduint256Token type identifier to purchase
amountuint256Quantity to purchase

_purchaseFor

Internal native currency purchase handler.

Validates, collects payment, refunds excess, mints tokens.

function _purchaseFor(address receiver, uint256 id, uint256 amount) internal virtual;

Parameters

NameTypeDescription
receiveraddressAddress to receive tokens
iduint256Token type identifier
amountuint256Quantity to purchase

_purchaseWithERC20For

Internal ERC-20 purchase handler.

Validates, checks balance/approval, transfers payment, mints tokens.

function _purchaseWithERC20For(address receiver, address paymentToken, uint256 id, uint256 amount) internal virtual;

Parameters

NameTypeDescription
receiveraddressAddress to receive tokens
paymentTokenaddressERC-20 contract address
iduint256Token type identifier
amountuint256Quantity to purchase

_setPrice

Internal function to set native currency price.

Price of 0 disables native currency purchases.

Note: emits: NativePriceSet

function _setPrice(uint256 id, uint256 price) internal virtual;

Parameters

NameTypeDescription
iduint256Token type identifier
priceuint256Native currency price

_setERC20Price

Internal function to set ERC-20 token price.

Price > 0 adds to accepted list, price = 0 removes from list.

Note: emits: ERC20PriceSet

function _setERC20Price(uint256 id, address token, uint256 price) internal virtual;

Parameters

NameTypeDescription
iduint256Token type identifier
tokenaddressERC-20 contract address
priceuint256Price in token units (0 to disable)

_setERC20Prices

Internal function to batch set ERC-20 prices.

Iterates through configs and sets each price.

function _setERC20Prices(uint256 id, PaymentToken[] calldata configs) internal virtual;

Parameters

NameTypeDescription
iduint256Token type identifier
configsPaymentToken[]Array of PaymentToken structs

_setTreasury

Internal function to update treasury address.

Validates address is not zero.

Note: emits: TreasuryUpdated

function _setTreasury(address payable account) internal virtual;

Parameters

NameTypeDescription
accountaddress payableNew treasury address

_validateReceiver

Validates recipient address is not zero.

Pure function for address validation.

Note: throws: InvalidReceiverAddress When receiver is zero

function _validateReceiver(address receiver) internal pure virtual;

Parameters

NameTypeDescription
receiveraddressAddress to validate

_validateAmount

Validates purchase quantity is not zero.

Pure function for amount validation.

Note: throws: InvalidTokenQuantity When amount is zero

function _validateAmount(uint256 amount) internal pure virtual;

Parameters

NameTypeDescription
amountuint256Quantity to validate

_completePurchase

Finalizes purchase by minting tokens and emitting event.

Calls abstract _mintPurchasedTokens function.

Note: emits: TokenPurchased

function _completePurchase(address receiver, uint256 id, uint256 amount, uint256 totalPrice) internal virtual;

Parameters

NameTypeDescription
receiveraddressAddress receiving tokens
iduint256Token type identifier
amountuint256Quantity purchased
totalPriceuint256Total payment collected

_mintPurchasedTokens

Abstract function to mint purchased tokens.

Must be implemented by inheriting contracts.

function _mintPurchasedTokens(address to, uint256 id, uint256 amount) internal virtual;

Parameters

NameTypeDescription
toaddressAddress to receive minted tokens
iduint256Token type identifier
amountuint256Quantity to mint

Events

TokenPurchased

Emitted when tokens are purchased.

event TokenPurchased(address caller, address indexed receiver, uint256 indexed id, uint256 amount, uint256 price);

Parameters

NameTypeDescription
calleraddressAddress initiating the purchase
receiveraddressAddress receiving the tokens
iduint256Token type identifier
amountuint256Quantity purchased
priceuint256Total payment amount

TreasuryUpdated

Emitted when treasury address changes.

event TreasuryUpdated(address caller, address indexed account);

Parameters

NameTypeDescription
calleraddressAddress making the change
accountaddressNew treasury address

NativePriceSet

Emitted when native currency price is updated.

event NativePriceSet(uint256 indexed id, uint256 price);

Parameters

NameTypeDescription
iduint256Token type identifier
priceuint256New price in native currency

ERC20PriceSet

Emitted when ERC-20 price is updated.

event ERC20PriceSet(uint256 indexed id, address indexed token, uint256 price);

Parameters

NameTypeDescription
iduint256Token type identifier
tokenaddressERC-20 contract address
priceuint256New price in token units

Errors

InsufficientERC20Allowance

Error for insufficient ERC-20 approval.

error InsufficientERC20Allowance(address token, uint256 required, uint256 allowance);

Parameters

NameTypeDescription
tokenaddressERC-20 contract address
requireduint256Amount needed
allowanceuint256Current approval amount

InsufficientERC20Balance

Error for insufficient ERC-20 balance.

error InsufficientERC20Balance(address token, uint256 required, uint256 balance);

Parameters

NameTypeDescription
tokenaddressERC-20 contract address
requireduint256Amount needed
balanceuint256Current balance

InsufficientPayment

Error for underpayment during purchase.

error InsufficientPayment(uint256 id, uint256 amount, uint256 price, uint256 paid);

Parameters

NameTypeDescription
iduint256Token type identifier
amountuint256Quantity attempted to purchase
priceuint256Total price required
paiduint256Amount actually paid

InvalidERC20PaymentToken

Error for unaccepted ERC-20 payment token.

error InvalidERC20PaymentToken(address token);

Parameters

NameTypeDescription
tokenaddressERC-20 contract address

InvalidTokenQuantity

Error for invalid purchase quantity.

error InvalidTokenQuantity(uint256 amount);

Parameters

NameTypeDescription
amountuint256The invalid amount specified

InvalidReceiverAddress

Error for invalid recipient address.

error InvalidReceiverAddress(address receiver);

Parameters

NameTypeDescription
receiveraddressThe invalid address specified

InvalidTreasuryAddress

Error for invalid treasury address.

error InvalidTreasuryAddress(address treasury);

Parameters

NameTypeDescription
treasuryaddressThe invalid address specified

TokenNotForSaleWithNativeCurrency

Error when token cannot be purchased with native currency.

error TokenNotForSaleWithNativeCurrency(uint256 id);

Parameters

NameTypeDescription
iduint256Token type identifier

TokenNotForSaleWithERC20

Error when token cannot be purchased with specific ERC-20.

error TokenNotForSaleWithERC20(uint256 id, address token);

Parameters

NameTypeDescription
iduint256Token type identifier
tokenaddressERC-20 contract address

Structs

PaymentToken

Payment option with token address and price.

struct PaymentToken {
    address token;
    uint256 price;
}

Properties

NameTypeDescription
tokenaddressERC-20 contract address
priceuint256Cost in token units

TokenPurchasableStorage

Note: storage-location: erc7201:tokenpurchasable.storage.TokenPurchasable

struct TokenPurchasableStorage {
    address payable treasury;
    mapping(uint256 => uint256) nativePrices;
    mapping(uint256 => mapping(address => uint256)) erc20Prices;
    mapping(uint256 => address[]) erc20TokensAccepted;
}