false
true
0
PulseChain
Blockchain
Blocks
Blocks
Uncles
Forked Blocks (Reorgs)
Transactions
Confirmed
Pending
Verified contracts
Tokens
All
PLS
APIs
GraphQL
RPC
Eth RPC
Apps
PulseChain Beacon Explorer
PulseX
PulseChain Bridge
Become a Validator
PulseChain
Mainnets
PulseChain Mainnet
Testnets
Testnet V4
/
Search
/
Search
Connection Lost
New Solidity Smart Contract Verification
Contract Address
The 0x address supplied on contract creation.
Is Yul contract
No
Yes
Select Yes if you want to verify Yul contract.
Contract Name
Must match the name specified in the code. For example, in
contract MyContract {..}
MyContract
is the contract name.
Include nightly builds
No
Yes
Select yes if you want to show nightly builds.
Compiler
v0.8.35+commit.47b9dedd
v0.8.35-pre.1+commit.a99b6d8c
v0.8.34+commit.80d5c536
v0.8.33+commit.64118f21
v0.8.32+commit.ebbd65e5
v0.8.31+commit.fd3a2265
v0.8.31-pre.1+commit.b59566f6
v0.8.30+commit.73712a01
v0.8.29+commit.ab55807c
v0.8.28+commit.7893614a
v0.8.27+commit.40a35a09
v0.8.26+commit.8a97fa7a
v0.8.25+commit.b61c2a91
v0.8.24+commit.e11b9ed9
v0.8.23+commit.f704f362
v0.8.22+commit.4fc1097e
v0.8.21+commit.d9974bed
v0.8.20+commit.a1b79de6
v0.8.19+commit.7dd6d404
v0.8.18+commit.87f61d96
v0.8.17+commit.8df45f5f
v0.8.16+commit.07a7930e
v0.8.15+commit.e14f2714
v0.8.14+commit.80d49f37
v0.8.13+commit.abaa5c0e
v0.8.12+commit.f00d7308
v0.8.11+commit.d7f03943
v0.8.10+commit.fc410830
v0.8.9+commit.e5eed63a
v0.8.8+commit.dddeac2f
v0.8.7+commit.e28d00a7
v0.8.6+commit.11564f7e
v0.8.5+commit.a4f2e591
v0.8.4+commit.c7e474f2
v0.8.3+commit.8d00100c
v0.8.2+commit.661d1103
v0.8.1+commit.df193b15
v0.8.0+commit.c7dfd78e
v0.7.6+commit.7338295f
v0.7.5+commit.eb77ed08
v0.7.4+commit.3f05b770
v0.7.3+commit.9bfce1f6
v0.7.2+commit.51b20bc0
v0.7.1+commit.f4a555be
v0.7.0+commit.9e61f92b
v0.6.12+commit.27d51765
v0.6.11+commit.5ef660b1
v0.6.10+commit.00c0fcaf
v0.6.9+commit.3e3065ac
v0.6.8+commit.0bbfe453
v0.6.7+commit.b8d736ae
v0.6.6+commit.6c089d02
v0.6.5+commit.f956cc89
v0.6.4+commit.1dca32f3
v0.6.3+commit.8dda9521
v0.6.2+commit.bacdbe57
v0.6.1+commit.e6f7d5a4
v0.6.0+commit.26b70077
v0.5.17+commit.d19bba13
v0.5.16+commit.9c3226ce
v0.5.15+commit.6a57276f
v0.5.14+commit.01f1aaa4
v0.5.13+commit.5b0b510c
v0.5.12+commit.7709ece9
v0.5.11+commit.22be8592
v0.5.10+commit.5a6ea5b1
v0.5.9+commit.c68bc34e
v0.5.8+commit.23d335f2
v0.5.7+commit.6da8b019
v0.5.6+commit.b259423e
v0.5.5+commit.47a71e8f
v0.5.4+commit.9549d8ff
v0.5.3+commit.10d17f24
v0.5.2+commit.1df8f40c
v0.5.1+commit.c8a2cb62
v0.5.0+commit.1d4f565a
v0.4.26+commit.4563c3fc
v0.4.25+commit.59dbf8f1
v0.4.24+commit.e67f0147
v0.4.23+commit.124ca40d
v0.4.22+commit.4cb486ee
v0.4.21+commit.dfe3193c
v0.4.20+commit.3155dd80
v0.4.19+commit.c4cbbb05
v0.4.18+commit.9cf6e910
v0.4.17+commit.bdeb9e52
v0.4.16+commit.d7661dd9
v0.4.15+commit.8b45bddb
v0.4.14+commit.c2215d46
v0.4.13+commit.0fb4cb1a
v0.4.12+commit.194ff033
v0.4.11+commit.68ef5810
v0.4.10+commit.9e8cc01b
The compiler version is specified in
pragma solidity X.X.X
. Use the compiler version rather than the nightly build. If using the Solidity compiler, run
solc —version
to check.
EVM Version
homestead
tangerineWhistle
spuriousDragon
byzantium
constantinople
petersburg
istanbul
berlin
london
paris
shanghai
default
The EVM version the contract is written for. If the bytecode does not match the version, we try to verify using the latest EVM version.
EVM version details
.
Optimization
No
Yes
If you enabled optimization during compilation, select yes.
Optimization runs
Enter the Solidity Contract Code
// File: @openzeppelin/contracts/security/ReentrancyGuard.sol // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } } // File: @openzeppelin/contracts/interfaces/draft-IERC6093.sol // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); } // File: @openzeppelin/contracts/utils/Context.sol // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); } // File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); } // File: @openzeppelin/contracts/token/ERC20/ERC20.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. */ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { mapping(address account => uint256) private _balances; mapping(address account => mapping(address spender => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows _totalSupply += value; } else { uint256 fromBalance = _balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. _balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. _totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. _balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * ``` * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } _allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner` s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } } // File: PulseCoinERC20Factory-calldata.sol /** * SPDX-License-Identifier: GPL-3.0 * * ██████╗ ██╗ ██╗██╗ ███████╗███████╗ ██████╗ ██████╗ ██╗███╗ ██╗ * ██╔══██╗██║ ██║██║ ██╔════╝██╔════╝██╔════╝██╔═══██╗██║████╗ ██║ * ██████╔╝██║ ██║██║ ███████╗█████╗ ██║ ██║ ██║██║██╔██╗ ██║ * ██╔═══╝ ██║ ██║██║ ╚════██║██╔══╝ ██║ ██║ ██║██║██║╚██╗██║ * ██║ ╚██████╔╝███████╗███████║███████╗╚██████╗╚██████╔╝██║██║ ╚████║ * ╚═╝ ╚═════╝ ╚══════╝╚══════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝╚═╝ ╚═══╝ * __ __ _ * \ \/ /___ __ _______ _________ (_)___ * \ / __ \/ / / / ___/ / ___/ __ \/ / __ \ * / / /_/ / /_/ / / / /__/ /_/ / / / / / * /_/\____/\__,_/_/ ____ \___/\____/_/_/ /_/________ _ * ____ ____ / __ \__ __/ /_______ / ____/ /_ ____ _(_)___ * / __ \/ __ \ / /_/ / / / / / ___/ _ \/ / / __ \/ __ `/ / __ \ * / /_/ / / / / / ____/ /_/ / (__ ) __/ /___/ / / / /_/ / / / / / * \____/_/ /_/ /_/ \__,_/_/____/\___/\____/_/ /_/\__,_/_/_/ /_/ * * @title PulseCoin ERC20 Factory Contract * @notice Manages the creation and lifecycle of ERC20 tokens with functionalities for minting, staking, and liquidity provisioning. * @dev This contract uses OpenZeppelin's ERC20 and ReentrancyGuard for token creation and reentrancy protection. * Released under the GNU General Public License v3.0. * * * Copyright (C) 2024 PulseCoin */ pragma solidity 0.8.24; /// @notice Interface for the Staking Contract used to handle airdrops and liquidity provisioning. /// @dev Functions declared in this interface are expected to be implemented by the staking contract, which should handle token distributions and staking logic. interface IStakingContract { /// @notice Receives tokens for airdrops and manages liquidity provisioning if required. /// @param _token The address of the token being airdropped. /// @param _amount The amount of the token to be airdropped. /// @param createLP Indicates whether liquidity provision is part of the airdrop. /// @param lpPercentage The percentage of the airdropped tokens that will be used for liquidity provision. /// @param useSnapshot Indicates whether to use a token snapshot for the distribution. function receiveAirdropTokens( address _token, uint256 _amount, bool createLP, uint8 lpPercentage, bool useSnapshot ) external payable; } /// @title ERC20 Token Template /// @notice Implements a template for creating ERC20 tokens with an initial supply allocated directly to a specified creator's address. /// @dev This contract extends the OpenZeppelin ERC20 standard implementation and includes additional functionality for setting a token creator during deployment. contract ERC20TokenTemplate is ERC20 { /// @notice Address of the token's creator, who receives the initial supply upon creation. address public tokenCreator; /// @notice Constructor that creates an ERC20 token and allocates the initial supply to the specified creator. /// @dev Mints the initial supply of tokens to the creator's address and assigns ownership of these tokens. /// @param _creator The address that will receive the initial token supply and is designated as the creator if the creator allocates more than 0 percent. /// @param name The name of the token, used in ERC20 token standard. /// @param symbol The symbol of the token, used in ERC20 token standard. /// @param initialSupply The amount of tokens to mint initially, which are allocated to the creator's address. constructor( address _creator, string memory name, string memory symbol, uint256 initialSupply ) ERC20(name, symbol) { tokenCreator = _creator; _mint(msg.sender, initialSupply); // Mint the initial supply to the ERC20Factory contract address } } /// @notice ERC20 Factory /// @notice Manages the creation and tracking of ERC20 tokens using the ERC20TokenTemplate. /// @dev Utilizes an enumerable set for storing token addresses and maintains detailed records of each token. contract PulseCoinERC20Factory is ReentrancyGuard { /// @notice Event emitted when a new ERC20 token is created. event TokenCreated(address indexed creator, address tokenAddress, string name, string symbol, uint256 initialSupply); /// @dev Set of all token addresses created by this factory. address[] public tokenAddresses; /// @dev Mapping from token addresses to their creator's address. mapping(address => address) public tokenCreators; /// @dev Mapping from token addresses to detailed records of token data. mapping(address => TokenDetails) public tokenDetails; /// @dev Structure to hold detailed information about each token. struct TokenDetails { uint256 totalSupply; uint256 creatorAmount; uint256 airdroppedAmount; uint256 lpAmount; address stakingContract; bool mintCompleted; uint8 creatorPercentage; uint8 airdropPercentage; uint8 lpPercentage; } /// @notice The address of the staking contract associated with this factory. address public stakingContractAddress; /// @dev Counter for the total number of tokens created by the factory. uint256 public totalTokensCreated; /// @notice Constructs a new ERC20Factory and sets the staking contract address. /// @param _stakingContractAddress The address of the staking contract that will interact with the tokens created by this factory. /// @dev The staking contract address must be non-zero. constructor(address _stakingContractAddress) { require(_stakingContractAddress != address(0), "Invalid staking contract address"); stakingContractAddress = _stakingContractAddress; } /// @notice Initiate the minting of a new ERC20 token /// @notice Creates a new ERC20 token with specified name, symbol, and initial supply, registering it under the creator's address. /// @dev Deploys a new ERC20TokenTemplate instance and logs the creation with an event. /// Validates the name, symbol, and initial supply to ensure they meet specific criteria for length and value. /// @param name The name of the new token to be created, must be non-empty and less than 100 characters. /// @param symbol The symbol of the new token, must be non-empty and less than 10 characters. /// @param initialSupply The amount of the token to be minted initially to the creator, must be greater than zero. /// @return tokenAddress The contract address of the newly minted token. function initiateMint(string calldata name, string calldata symbol, uint256 initialSupply) external nonReentrant returns (address tokenAddress) { require(bytes(name).length > 0 && bytes(name).length <= 100, "Invalid name: must be 1-100 characters long"); require(bytes(symbol).length > 0 && bytes(symbol).length <= 10, "Invalid symbol: must be 1-10 characters long"); require(initialSupply > 0, "Invalid initial supply: must be greater than zero"); ERC20TokenTemplate newToken = new ERC20TokenTemplate(msg.sender, name, symbol, initialSupply); tokenAddress = address(newToken); tokenAddresses.push(tokenAddress); tokenCreators[tokenAddress] = msg.sender; totalTokensCreated++; emit TokenCreated(msg.sender, tokenAddress, name, symbol, initialSupply); return tokenAddress; } /// @notice Complete the minting process for a newly created ERC20 token /// @notice Finalizes token distribution including allocations for the creator, staking, and liquidity provision, and records the token details. /// @dev This function handles the distribution of tokens post-creation and must be called by the token's creator. /// @param tokenAddress The address of the newly minted token. /// @param provideLiquidity Flag indicating whether liquidity should be provided. /// @param lpPercentage The percentage of the remaining supply to be allocated for liquidity provision. /// @param creatorPercentage The percentage of the total supply allocated to the token's creator. /// @param useSnapshot Flag indicating whether to use a snapshot mechanism for the token distribution in staking. /// @dev Requires the caller to be the token creator and the token address to be valid. /// Throws if the remaining supply is less than the minimum required for staking allocation. function completeMint( address tokenAddress, bool provideLiquidity, uint8 lpPercentage, uint8 creatorPercentage, bool useSnapshot ) external nonReentrant payable { validateCommonConditions(tokenAddress, lpPercentage, creatorPercentage); ERC20TokenTemplate token = ERC20TokenTemplate(tokenAddress); uint256 totalSupply = token.totalSupply(); uint256 creatorAllocation = totalSupply * creatorPercentage / 100; uint256 remainingSupply = totalSupply - creatorAllocation; _completeMintCommon(tokenAddress, totalSupply, creatorAllocation, remainingSupply, provideLiquidity, lpPercentage, useSnapshot, creatorPercentage); } /// @notice Finalizes token minting by distributing tokens to the creator, for liquidity, and staking, and allocates a bonus to a referral address. /// @dev This function extends `completeMint` to include processing a referral bonus. /// @param tokenAddress The address of the token for which minting is being completed. /// @param provideLiquidity Indicates if liquidity should be provided from the remaining token supply. /// @param lpPercentage Defines the percentage of the post-creator allocated supply that should be directed towards liquidity. /// @param creatorPercentage Defines the percentage of the total token supply that should be allocated to the token creator. /// @param useSnapshot Indicates if token distribution should use a snapshot for fairness in distribution, primarily in staking scenarios. /// @param referralAddress The address of the referral recipient who will receive a bonus allocation. function completeMintReferral( address tokenAddress, bool provideLiquidity, uint8 lpPercentage, uint8 creatorPercentage, bool useSnapshot, address referralAddress ) external nonReentrant payable { validateCommonConditions(tokenAddress, lpPercentage, creatorPercentage); require(referralAddress != address(0), "Invalid referral address"); ERC20TokenTemplate token = ERC20TokenTemplate(tokenAddress); uint256 totalSupply = token.totalSupply(); uint256 referralAllocation = totalSupply * 9 / 10000; // 0.09% of the total supply token.transfer(referralAddress, referralAllocation); uint256 creatorAllocation = totalSupply * creatorPercentage / 100; uint256 remainingSupply = totalSupply - creatorAllocation - referralAllocation; _completeMintCommon(tokenAddress, totalSupply, creatorAllocation, remainingSupply, provideLiquidity, lpPercentage, useSnapshot, creatorPercentage); } /// @dev Centralizes the minting completion logic, handling token distributions and setting final token details. /// @param tokenAddress The ERC20 token address for which minting is being completed. /// @param totalSupply The total supply of tokens for the given token address. /// @param creatorAllocation The amount of tokens allocated to the token's creator. /// @param remainingSupply The supply of tokens left after the creator's allocation. /// @param provideLiquidity Indicates whether part of the remaining tokens should be allocated for liquidity. /// @param lpPercentage The percentage of the remaining supply that should be allocated for liquidity if liquidity is provided. /// @param useSnapshot Indicates whether to use a token snapshot for distributing tokens in staking. /// @param creatorPercentage The percentage of total supply allocated to the creator; used for recording in token details. /// Handles token approval for staking, calculates and processes staking and liquidity allocations, and updates token record details. function _completeMintCommon( address tokenAddress, uint256 totalSupply, uint256 creatorAllocation, uint256 remainingSupply, bool provideLiquidity, uint8 lpPercentage, bool useSnapshot, uint8 creatorPercentage ) internal { uint256 minimumStakingAllocation = totalSupply * 369 / 100000; require(remainingSupply >= minimumStakingAllocation, "Staking allocation is too low"); ERC20TokenTemplate(tokenAddress).approve(stakingContractAddress, remainingSupply); uint256 stakingAllocation = calculateStakingAllocation(remainingSupply, provideLiquidity, lpPercentage); uint256 lpAmount = remainingSupply - stakingAllocation; if (stakingAllocation > 0) { IStakingContract(stakingContractAddress).receiveAirdropTokens{value: msg.value}( tokenAddress, stakingAllocation, provideLiquidity, lpPercentage, useSnapshot ); } if (creatorAllocation > 0) { ERC20TokenTemplate(tokenAddress).transfer(ERC20TokenTemplate(tokenAddress).tokenCreator(), creatorAllocation); } // Calculate airdrop percentage and ensure it does not exceed 100% uint256 calculatedAirdropPercentage = 100 * stakingAllocation / totalSupply; require(calculatedAirdropPercentage <= 100, "Airdrop percentage exceeds 100"); // Store token details tokenDetails[tokenAddress] = TokenDetails({ totalSupply: totalSupply, creatorAmount: creatorAllocation, airdroppedAmount: stakingAllocation, lpAmount: lpAmount, stakingContract: stakingContractAddress, mintCompleted: true, creatorPercentage: creatorPercentage, airdropPercentage: uint8(calculatedAirdropPercentage), lpPercentage: lpPercentage }); } /// @dev Validates common preconditions for mint completion functions. function validateCommonConditions(address tokenAddress, uint8 lpPercentage, uint8 creatorPercentage) internal view { require(tokenAddress != address(0), "Invalid token address"); require(msg.sender == ERC20TokenTemplate(tokenAddress).tokenCreator(), "Not authorized"); require(lpPercentage <= 100, "Invalid LP percentage: must be 0-100"); require(creatorPercentage <= 100, "Invalid creator percentage: must be 0-100"); require(lpPercentage + creatorPercentage <= 100, "Combined LP and creator percentages must not exceed 100%"); } /// @notice Calculate Staking Allocation /// @dev Calculates the allocation for staking from the remaining supply after allocations for liquidity and creator shares. /// @param remainingSupply The amount of tokens remaining after deducting the creator's allocation. /// @param provideLiquidity A boolean indicating whether liquidity should be provided from the remaining tokens. /// @param lpPercentage The percentage of the remaining supply that should be allocated for liquidity if `provideLiquidity` is true. /// @return stakingAllocation The final amount of tokens available for staking, after deducting liquidity allocation if applicable. function calculateStakingAllocation( uint256 remainingSupply, bool provideLiquidity, uint8 lpPercentage ) private pure returns (uint256 stakingAllocation) { if (provideLiquidity && lpPercentage > 0) { uint256 lpAllocation = remainingSupply * lpPercentage / 100; return remainingSupply - lpAllocation; } return remainingSupply; } /// @notice Returns the balance of tokens held by the factory for a specific token /// @param tokenAddress Address of the token /// @return The balance of tokens held by this factory function getTokenBalance(address tokenAddress) external view returns (uint256) { ERC20TokenTemplate token = ERC20TokenTemplate(tokenAddress); return token.balanceOf(address(this)); } /// @notice Returns the total number of tokens created by the factory /// @return The total number of tokens created function getTotalCreatedTokens() external view returns (uint256) { return totalTokensCreated; } /// @notice Retrieves the address and creator of a token by its index in the storage array /// @param index Index of the token in the `tokenAddresses` array /// @return tokenAddress Address of the token /// @return creator Address of the token's creator function getTokenByIndex(uint256 index) external view returns (address tokenAddress, address creator) { require(index < tokenAddresses.length, "Index out of bounds"); tokenAddress = tokenAddresses[index]; creator = tokenCreators[tokenAddress]; } /// @dev Allows the contract to receive Ether receive() external payable {} }
We recommend using flattened code. This is necessary if your code utilizes a library or inherits dependencies. Use the
POA solidity flattener or the
truffle flattener
.
Try to fetch constructor arguments automatically
No
Yes
ABI-encoded Constructor Arguments (if required by the contract)
0x0000000000000000000000007c4f019f123319376b94cf51328c1a999ddb438d000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000031a17e847807b1bc00000000000000000000000000000000000000000000000000000000000000000000084c6f7665636f696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024c43000000000000000000000000000000000000000000000000000000000000
Add arguments in
ABI hex encoded form
. Constructor arguments are written right to left, and will be found at the end of the input created bytecode. They may also be
parsed here.
Add Contract Libraries
Contract Libraries
Library 1 Name
A library name called in the .sol file. Multiple libraries (up to 10) may be added for each contract. Click the Add Library button to add an additional one.
Library 1 Address
The 0x library address. This can be found in the generated json file or Truffle output (if using truffle).
Library 2 Name
Library 2 Address
Library 3 Name
Library 3 Address
Library 4 Name
Library 4 Address
Library 5 Name
Library 5 Address
Library 6 Name
Library 6 Address
Library 7 Name
Library 7 Address
Library 8 Name
Library 8 Address
Library 9 Name
Library 9 Address
Library 10 Name
Library 10 Address
Add Library
Loading...
Verify & publish
Cancel
Ok
Ok
Ok
No
Yes