Easily deploy your ERC20 token on Quai Network.
Enter the name of your token.
Enter your token ticker.
Set the intitial supply of your token.
The ERC20 Contract
The Quai Token deployer is configured to deploy the base implementation of Open Zeppelin's ERC20 standard expanded with a Ownable modifier contract. Deploying the contract will create a new single-chain token with the specified name, symbol, and supply. You, as the owner, will be minted the entirety of the token supply, and will be able to mint new tokens and transfer ownership of the token contract.
While the contract below is useful for simple deployments, it lacks customizability. If your token requires more advanced features such as custom distribution, consider writing your own contract and deploying it via Hardhat.
erc20.sol
1// SPDX-License-Identifier: MIT23pragma solidity 0.8.17;45import "./Address.sol";6import "./IERC20.sol";7import "./IERC20Metadata.sol";8import "./EIP712.sol";9import "./Nonces.sol";10import "./IERC20Permit.sol";11import "./ECDSA.sol";1213contract ERC20 is IERC20, IERC20Metadata, IERC20Permit, EIP712, Nonces {14using Address for address;1516bytes32 private constant PERMIT_TYPEHASH =17keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");1819/**20* @dev Permit deadline has expired.21*/22error ERC2612ExpiredSignature(uint256 deadline);2324/**25* @dev Mismatched signature.26*/27error ERC2612InvalidSigner(address signer, address owner);2829mapping(address => uint256) private _balances;30mapping(address => mapping(address => uint256)) private _allowances;31uint256 private _totalSupply;32string private _name;33string private _symbol;3435constructor(36string memory name_,37string memory symbol_,38uint256 totalSupply_39) EIP712(name_, "1") {40_name = name_;41_symbol = symbol_;42_mint(msg.sender, totalSupply_);43}4445function name() public view virtual override returns (string memory) {46return _name;47}4849function symbol() public view virtual override returns (string memory) {50return _symbol;51}5253function decimals() public view virtual override returns (uint8) {54return 18;55}5657function totalSupply() public view virtual override returns (uint256) {58return _totalSupply;59}6061function balanceOf(62address account63) public view virtual override returns (uint256) {64return _balances[account];65}6667function transferFrom(68address sender,69address recipient,70uint256 amount71) public virtual override returns (bool) {72_transfer(sender, recipient, amount);7374uint256 currentAllowance = _allowances[sender][msg.sender];75require(76currentAllowance >= amount,77"ERC20: transfer amount exceeds allowance"78);79unchecked {80_approve(sender, msg.sender, currentAllowance - amount);81}8283return true;84}8586function transfer(87address recipient,88uint256 amount89) public virtual override returns (bool) {90_transfer(msg.sender, recipient, amount);91return true;92}9394function allowance(95address owner,96address spender97) public view virtual override returns (uint256) {98return _allowances[owner][spender];99}100101function approve(102address spender,103uint256 amount104) public virtual override returns (bool) {105_approve(msg.sender, spender, amount);106return true;107}108109function decreaseAllowance(110address spender,111uint256 subtractedValue112) public virtual returns (bool) {113uint256 currentAllowance = _allowances[msg.sender][spender];114require(115currentAllowance >= subtractedValue,116"ERC20: decreased allowance below zero"117);118unchecked {119_approve(msg.sender, spender, currentAllowance - subtractedValue);120}121122return true;123}124125function increaseAllowance(126address spender,127uint256 addedValue128) public virtual returns (bool) {129_approve(130msg.sender,131spender,132_allowances[msg.sender][spender] + addedValue133);134return true;135}136137function _transfer(138address sender,139address recipient,140uint256 amount141) internal virtual {142require(sender != address(0), "ERC20: transfer from the zero address");143require(recipient != address(0), "ERC20: transfer to the zero address");144145uint256 senderBalance = _balances[sender];146require(147senderBalance >= amount,148"ERC20: transfer amount exceeds balance"149);150unchecked {151_balances[sender] = senderBalance - amount;152}153_balances[recipient] += amount;154155emit Transfer(sender, recipient, amount);156}157158function _mint(address account, uint256 amount) internal virtual {159require(account != address(0), "ERC20: mint to the zero address");160161_totalSupply += amount;162_balances[account] += amount;163emit Transfer(address(0), account, amount);164}165166function _burn(address account, uint256 amount) internal virtual {167require(account != address(0), "ERC20: burn from the zero address");168169uint256 accountBalance = _balances[account];170require(accountBalance >= amount, "ERC20: burn amount exceeds balance");171unchecked {172_balances[account] = accountBalance - amount;173}174_totalSupply -= amount;175176emit Transfer(account, address(0), amount);177}178179function _approve(180address owner,181address spender,182uint256 amount183) internal virtual {184require(owner != address(0), "ERC20: approve from the zero address");185require(spender != address(0), "ERC20: approve to the zero address");186187_allowances[owner][spender] = amount;188emit Approval(owner, spender, amount);189}190191/**192* @inheritdoc IERC20Permit193*/194function permit(195address owner,196address spender,197uint256 value,198uint256 deadline,199uint8 v,200bytes32 r,201bytes32 s202) public virtual {203if (block.timestamp > deadline) {204revert ERC2612ExpiredSignature(deadline);205}206207bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));208209bytes32 hash = _hashTypedDataV4(structHash);210211address signer = ECDSA.recover(hash, v, r, s);212if (signer != owner) {213revert ERC2612InvalidSigner(signer, owner);214}215216_approve(owner, spender, value);217}218219/**220* @inheritdoc IERC20Permit221*/222function nonces(address owner) public view virtual override(IERC20Permit, Nonces) returns (uint256) {223return super.nonces(owner);224}225226/**227* @inheritdoc IERC20Permit228*/229// solhint-disable-next-line func-name-mixedcase230function DOMAIN_SEPARATOR() external view virtual returns (bytes32) {231return _domainSeparatorV4();232}233}