Description:
ERC20 token contract with Burnable, Factory capabilities. Standard implementation for fungible tokens on Ethereum.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"src/OpMev.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
import {ERC20} from "@superopevm/contracts/token/ERC20/ERC20.sol";
import {ERC20Burnable} from "@superopevm/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import {ERC20PermitWithSignatureChecker} from "@superopevm/contracts/token/ERC20/extensions/ERC20PermitWithSignatureChecker.sol";
/**
* @title OpMev
* @dev ERC20 token Custom SuperOpMev
*/
contract OpMev is ERC20, ERC20Burnable, ERC20PermitWithSignatureChecker {
constructor(uint256 initialSupply)
ERC20("Op Mev", "OV")
ERC20PermitWithSignatureChecker("Op Mev")
{
_mint(msg.sender, initialSupply);
}
}
"
},
"lib/superopevm/contracts/token/ERC20/ERC20.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
import {IERC20 as IERC20} from "@superopevm/contracts/interfaces/IERC20.sol";
import {IERC20Metadata as IERC20Metadata} from "@superopevm/contracts/interfaces/IERC20Metadata.sol";
import {Context as Context} from "@superopevm/contracts/utils/Context.sol";
/**
* @dev Implementation of the ERC20 standard
*/
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
unchecked {
_approve(sender, _msgSender(), currentAllowance - amount);
}
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
uint256 currentAllowance = _allowances[_msgSender()][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(_msgSender(), spender, currentAllowance - subtractedValue);
}
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[sender] = senderBalance - amount;
}
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
_afterTokenTransfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}
"
},
"lib/superopevm/contracts/token/ERC20/extensions/ERC20Burnable.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
import {ERC20 as ERC20} from "@superopevm/contracts/token/ERC20/ERC20.sol";
import {Context as Context} from "@superopevm/contracts/utils/Context.sol";
/**
* @dev Extension of ERC20 that allows token holders to destroy tokens
*/
abstract contract ERC20Burnable is Context, ERC20 {
function burn(uint256 amount) public virtual {
_burn(_msgSender(), amount);
}
function burnFrom(address account, uint256 amount) public virtual {
uint256 currentAllowance = allowance(account, _msgSender());
require(currentAllowance >= amount, "ERC20: burn amount exceeds allowance");
unchecked {
_approve(account, _msgSender(), currentAllowance - amount);
}
_burn(account, amount);
}
}
"
},
"lib/superopevm/contracts/token/ERC20/extensions/ERC20PermitWithSignatureChecker.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
import {IERC20Permit as IERC20Permit} from "@superopevm/contracts/interfaces/IERC20Permit.sol";
import {ERC20 as ERC20} from "@superopevm/contracts/token/ERC20/ERC20.sol";
import {SignatureChecker as SignatureChecker} from "@superopevm/contracts/utils/cryptography/SignatureChecker.sol";
import {Counters as Counters} from "@superopevm/contracts/utils/math/Counters.sol";
import {EIP712 as EIP712} from "@superopevm/contracts/utils/cryptography/EIP712.sol";
/**
* @title ERC20PermitWithSignatureChecker
* @dev ERC20Permit implementation using SignatureChecker
*/
abstract contract ERC20PermitWithSignatureChecker is ERC20, IERC20Permit, EIP712 {
using Counters for Counters.Counter;
mapping(address => Counters.Counter) private _nonces;
bytes32 private constant _PERMIT_TYPEHASH =
keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
constructor(string memory name) EIP712(name, "1") {}
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual override(IERC20Permit) {
require(block.timestamp <= deadline, "ERC20Permit: expired deadline");
bytes32 structHash = keccak256(
abi.encode(
_PERMIT_TYPEHASH,
owner,
spender,
value,
_nonces[owner].current(),
deadline
)
);
bytes32 hash = _hashTypedDataV4(structHash);
require(SignatureChecker.isValidSignatureNow(owner, hash, v, r, s), "ERC20Permit: invalid signature");
_nonces[owner].increment();
_approve(owner, spender, value);
}
function nonces(address owner) public view virtual override(IERC20Permit) returns (uint256) {
return _nonces[owner].current();
}
function DOMAIN_SEPARATOR() public view virtual override(EIP712, IERC20Permit) returns (bytes32) {
return EIP712.DOMAIN_SEPARATOR();
}
}
"
},
"lib/superopevm/contracts/interfaces/IERC20.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
/**
* @dev Interface of the ERC20 standard
*/
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
"
},
"lib/superopevm/contracts/interfaces/IERC20Metadata.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
import {IERC20 as IERC20} from "@superopevm/contracts/interfaces/IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard
*/
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
"
},
"lib/superopevm/contracts/utils/Context.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
/**
* @dev Provides information about the current execution context
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
"
},
"lib/superopevm/contracts/interfaces/IERC20Permit.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
/**
* @title IERC20Permit
* @dev Interface for the Permit functionality (EIP-2612)
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,
* given `owner`'s signed approval.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature.
*/
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
"
},
"lib/superopevm/contracts/utils/cryptography/SignatureChecker.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
import {ECDSA as ECDSA} from "@superopevm/contracts/utils/cryptography/ECDSA.sol";
/**
* @title SignatureChecker
* @dev Helper for verifying signatures
*/
library SignatureChecker {
function isValidSignatureNow(
address signer,
bytes32 hash,
bytes memory signature
) internal view returns (bool) {
(address recovered, ECDSA.RecoverError error) = ECDSA.recover(hash, signature);
return (error == ECDSA.RecoverError.NoError && recovered == signer);
}
function isValidSignatureNow(
address signer,
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal view returns (bool) {
(address recovered, ECDSA.RecoverError error) = ECDSA.recover(hash, v, r, s);
return (error == ECDSA.RecoverError.NoError && recovered == signer);
}
}
"
},
"lib/superopevm/contracts/utils/math/Counters.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
/**
* @title Counters
* @dev Provides counters that can only be incremented or decremented by one.
*/
library Counters {
struct Counter {
uint256 _value;
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
unchecked {
counter._value += 1;
}
}
function decrement(Counter storage counter) internal {
uint256 value = counter._value;
require(value > 0, "Counters: decrement overflow");
unchecked {
counter._value = value - 1;
}
}
function reset(Counter storage counter) internal {
counter._value = 0;
}
}
"
},
"lib/superopevm/contracts/utils/cryptography/EIP712.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
/**
* @title EIP712
* @dev Helper for EIP-712 typed data hashing and signing
*/
abstract contract EIP712 {
bytes32 private immutable _HASHED_NAME;
bytes32 private immutable _HASHED_VERSION;
bytes32 private immutable _TYPE_HASH;
bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
uint256 private immutable _CACHED_CHAIN_ID;
address private immutable _CACHED_THIS;
constructor(string memory name, string memory version) {
bytes32 hashedName = keccak256(bytes(name));
bytes32 hashedVersion = keccak256(bytes(version));
bytes32 typeHash = keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
_HASHED_NAME = hashedName;
_HASHED_VERSION = hashedVersion;
_CACHED_CHAIN_ID = block.chainid;
_CACHED_THIS = address(this);
_TYPE_HASH = typeHash;
_CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {
return _CACHED_DOMAIN_SEPARATOR;
} else {
return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
}
}
function _buildDomainSeparator(
bytes32 typeHash,
bytes32 nameHash,
bytes32 versionHash
) private view returns (bytes32) {
return keccak256(
abi.encode(
typeHash,
nameHash,
versionHash,
block.chainid,
address(this)
)
);
}
function _hashTypedDataV4(bytes32 structHash) internal view returns (bytes32) {
return keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
structHash
)
);
}
}
"
},
"lib/superopevm/contracts/utils/cryptography/ECDSA.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
/**
* @title ECDSA
* @dev Elliptic Curve Digital Signature Algorithm operations
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV
}
function recover(
bytes32 hash,
bytes memory signature
) internal pure returns (address, RecoverError) {
if (signature.length != 65) {
return (address(0), RecoverError.InvalidSignatureLength);
}
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return recover(hash, v, r, s);
}
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v != 27 && v != 28) {
return (address(0), RecoverError.InvalidSignatureV);
}
return (tryRecover(hash, v, r, s), RecoverError.NoError);
}
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
bytes32 digest = keccak256(
abi.encodePacked("\x19Ethereum Signed Message:\
32", hash)
);
return ecrecover(digest, v, r, s);
}
function toEthSignedMessageHash(
bytes32 hash
) internal pure returns (bytes32) {
return keccak256(
abi.encodePacked("\x19Ethereum Signed Message:\
32", hash)
);
}
}
"
}
},
"settings": {
"remappings": [
"@superopevm/=lib/superopevm/",
"forge-std/=lib/forge-std/src/",
"superopevm/=lib/superopevm/contracts/"
],
"optimizer": {
"enabled": false,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "prague",
"viaIR": false
}
}}
Submitted on: 2025-09-24 13:59:09
Comments
Log in to comment.
No comments yet.