TokenPurchasable
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
Name | Type | Description |
---|---|---|
$ | TokenPurchasableStorage | Storage pointer to TokenPurchasableStorage struct |
__TokenPurchasable_init
Internal initializer for TokenPurchasable setup.
Sets initial treasury address.
function __TokenPurchasable_init(address payable initialTreasury) internal onlyInitializing;
Parameters
Name | Type | Description |
---|---|---|
initialTreasury | address payable | Address 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
Name | Type | Description |
---|---|---|
initialTreasury | address payable | Address 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
Name | Type | Description |
---|---|---|
id | uint256 | Token type identifier |
Returns
Name | Type | Description |
---|---|---|
price | uint256 | Native 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
Name | Type | Description |
---|---|---|
id | uint256 | Token type identifier |
Returns
Name | Type | Description |
---|---|---|
prices | PaymentToken[] | 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
Name | Type | Description |
---|---|---|
<none> | address | Treasury 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
Name | Type | Description |
---|---|---|
id | uint256 | Token type identifier to purchase |
amount | uint256 | Quantity 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
Name | Type | Description |
---|---|---|
receiver | address | Address to receive purchased tokens |
id | uint256 | Token type identifier to purchase |
amount | uint256 | Quantity 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
Name | Type | Description |
---|---|---|
paymentToken | address | ERC-20 contract address for payment |
id | uint256 | Token type identifier to purchase |
amount | uint256 | Quantity 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
Name | Type | Description |
---|---|---|
receiver | address | Address to receive purchased tokens |
paymentToken | address | ERC-20 contract address for payment |
id | uint256 | Token type identifier to purchase |
amount | uint256 | Quantity 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
Name | Type | Description |
---|---|---|
receiver | address | Address to receive tokens |
id | uint256 | Token type identifier |
amount | uint256 | Quantity 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
Name | Type | Description |
---|---|---|
receiver | address | Address to receive tokens |
paymentToken | address | ERC-20 contract address |
id | uint256 | Token type identifier |
amount | uint256 | Quantity 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
Name | Type | Description |
---|---|---|
id | uint256 | Token type identifier |
price | uint256 | Native 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
Name | Type | Description |
---|---|---|
id | uint256 | Token type identifier |
token | address | ERC-20 contract address |
price | uint256 | Price 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
Name | Type | Description |
---|---|---|
id | uint256 | Token type identifier |
configs | PaymentToken[] | 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
Name | Type | Description |
---|---|---|
account | address payable | New 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
Name | Type | Description |
---|---|---|
receiver | address | Address 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
Name | Type | Description |
---|---|---|
amount | uint256 | Quantity 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
Name | Type | Description |
---|---|---|
receiver | address | Address receiving tokens |
id | uint256 | Token type identifier |
amount | uint256 | Quantity purchased |
totalPrice | uint256 | Total 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
Name | Type | Description |
---|---|---|
to | address | Address to receive minted tokens |
id | uint256 | Token type identifier |
amount | uint256 | Quantity to mint |
Events
TokenPurchased
Emitted when tokens are purchased.
event TokenPurchased(address caller, address indexed receiver, uint256 indexed id, uint256 amount, uint256 price);
Parameters
Name | Type | Description |
---|---|---|
caller | address | Address initiating the purchase |
receiver | address | Address receiving the tokens |
id | uint256 | Token type identifier |
amount | uint256 | Quantity purchased |
price | uint256 | Total payment amount |
TreasuryUpdated
Emitted when treasury address changes.
event TreasuryUpdated(address caller, address indexed account);
Parameters
Name | Type | Description |
---|---|---|
caller | address | Address making the change |
account | address | New treasury address |
NativePriceSet
Emitted when native currency price is updated.
event NativePriceSet(uint256 indexed id, uint256 price);
Parameters
Name | Type | Description |
---|---|---|
id | uint256 | Token type identifier |
price | uint256 | New price in native currency |
ERC20PriceSet
Emitted when ERC-20 price is updated.
event ERC20PriceSet(uint256 indexed id, address indexed token, uint256 price);
Parameters
Name | Type | Description |
---|---|---|
id | uint256 | Token type identifier |
token | address | ERC-20 contract address |
price | uint256 | New price in token units |
Errors
InsufficientERC20Allowance
Error for insufficient ERC-20 approval.
error InsufficientERC20Allowance(address token, uint256 required, uint256 allowance);
Parameters
Name | Type | Description |
---|---|---|
token | address | ERC-20 contract address |
required | uint256 | Amount needed |
allowance | uint256 | Current approval amount |
InsufficientERC20Balance
Error for insufficient ERC-20 balance.
error InsufficientERC20Balance(address token, uint256 required, uint256 balance);
Parameters
Name | Type | Description |
---|---|---|
token | address | ERC-20 contract address |
required | uint256 | Amount needed |
balance | uint256 | Current balance |
InsufficientPayment
Error for underpayment during purchase.
error InsufficientPayment(uint256 id, uint256 amount, uint256 price, uint256 paid);
Parameters
Name | Type | Description |
---|---|---|
id | uint256 | Token type identifier |
amount | uint256 | Quantity attempted to purchase |
price | uint256 | Total price required |
paid | uint256 | Amount actually paid |
InvalidERC20PaymentToken
Error for unaccepted ERC-20 payment token.
error InvalidERC20PaymentToken(address token);
Parameters
Name | Type | Description |
---|---|---|
token | address | ERC-20 contract address |
InvalidTokenQuantity
Error for invalid purchase quantity.
error InvalidTokenQuantity(uint256 amount);
Parameters
Name | Type | Description |
---|---|---|
amount | uint256 | The invalid amount specified |
InvalidReceiverAddress
Error for invalid recipient address.
error InvalidReceiverAddress(address receiver);
Parameters
Name | Type | Description |
---|---|---|
receiver | address | The invalid address specified |
InvalidTreasuryAddress
Error for invalid treasury address.
error InvalidTreasuryAddress(address treasury);
Parameters
Name | Type | Description |
---|---|---|
treasury | address | The invalid address specified |
TokenNotForSaleWithNativeCurrency
Error when token cannot be purchased with native currency.
error TokenNotForSaleWithNativeCurrency(uint256 id);
Parameters
Name | Type | Description |
---|---|---|
id | uint256 | Token type identifier |
TokenNotForSaleWithERC20
Error when token cannot be purchased with specific ERC-20.
error TokenNotForSaleWithERC20(uint256 id, address token);
Parameters
Name | Type | Description |
---|---|---|
id | uint256 | Token type identifier |
token | address | ERC-20 contract address |
Structs
PaymentToken
Payment option with token address and price.
struct PaymentToken {
address token;
uint256 price;
}
Properties
Name | Type | Description |
---|---|---|
token | address | ERC-20 contract address |
price | uint256 | Cost 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;
}