ERC20 factory
This commit is contained in:
70
contracts/Factory/ERC20Factory.sol
Normal file
70
contracts/Factory/ERC20Factory.sol
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.6.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import {Ownable} from "../lib/Ownable.sol";
|
||||
import {ICloneFactory} from "../lib/CloneFactory.sol";
|
||||
import {IConstFeeRateModel} from "../lib/ConstFeeRateModel.sol";
|
||||
import {IDVM} from "../DODOVendingMachine/intf/IDVM.sol";
|
||||
import {IDVMAdmin} from "../DODOVendingMachine/intf/IDVMAdmin.sol";
|
||||
import {IPermissionManager} from "../lib/PermissionManager.sol";
|
||||
import {InitializableERC20} from "../external/ERC20/InitializableERC20.sol";
|
||||
import {InitializableMintableERC20} from "../external/ERC20/InitializableMintableERC20.sol";
|
||||
|
||||
contract ERC20Factory is Ownable {
|
||||
// ============ Templates ============
|
||||
|
||||
address public _CLONE_FACTORY_;
|
||||
address public _ERC20_TEMPLATE_;
|
||||
address public _MINTABLE_ERC20_TEMPLATE_;
|
||||
|
||||
// ============ Events ============
|
||||
|
||||
event NewERC20(address indexed erc20, address indexed creator, bool isMintable);
|
||||
|
||||
// ============ Functions ============
|
||||
|
||||
constructor(
|
||||
address cloneFactory,
|
||||
address erc20Template,
|
||||
address mintableErc20Template
|
||||
) public {
|
||||
_CLONE_FACTORY_ = cloneFactory;
|
||||
_ERC20_TEMPLATE_ = erc20Template;
|
||||
_MINTABLE_ERC20_TEMPLATE_ = mintableErc20Template;
|
||||
}
|
||||
|
||||
function createStdERC20(
|
||||
uint256 totalSupply,
|
||||
string memory name,
|
||||
string memory symbol,
|
||||
uint256 decimals
|
||||
) external returns (address newERC20) {
|
||||
newERC20 = ICloneFactory(_CLONE_FACTORY_).clone(_ERC20_TEMPLATE_);
|
||||
InitializableERC20(newERC20).init(msg.sender, totalSupply, name, symbol, decimals);
|
||||
emit NewERC20(newERC20, msg.sender, false);
|
||||
}
|
||||
|
||||
function createMintableERC20(
|
||||
uint256 initSupply,
|
||||
string memory name,
|
||||
string memory symbol,
|
||||
uint256 decimals
|
||||
) external returns (address newMintableERC20) {
|
||||
newMintableERC20 = ICloneFactory(_CLONE_FACTORY_).clone(_MINTABLE_ERC20_TEMPLATE_);
|
||||
InitializableMintableERC20(newMintableERC20).init(
|
||||
msg.sender,
|
||||
initSupply,
|
||||
name,
|
||||
symbol,
|
||||
decimals
|
||||
);
|
||||
emit NewERC20(newMintableERC20, msg.sender, true);
|
||||
}
|
||||
}
|
||||
83
contracts/external/ERC20/InitializableERC20.sol
vendored
Normal file
83
contracts/external/ERC20/InitializableERC20.sol
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.6.9;
|
||||
|
||||
import {SafeMath} from "../../lib/SafeMath.sol";
|
||||
|
||||
contract InitializableERC20 {
|
||||
using SafeMath for uint256;
|
||||
|
||||
string public name;
|
||||
uint256 public decimals;
|
||||
string public symbol;
|
||||
uint256 public totalSupply;
|
||||
|
||||
bool public initialized;
|
||||
|
||||
mapping(address => uint256) balances;
|
||||
mapping(address => mapping(address => uint256)) internal allowed;
|
||||
|
||||
event Transfer(address indexed from, address indexed to, uint256 amount);
|
||||
event Approval(address indexed owner, address indexed spender, uint256 amount);
|
||||
|
||||
function init(
|
||||
address _creator,
|
||||
uint256 _totalSupply,
|
||||
string memory _name,
|
||||
string memory _symbol,
|
||||
uint256 _decimals
|
||||
) public {
|
||||
require(!initialized, "TOKEN_INITIALIZED");
|
||||
initialized = true;
|
||||
totalSupply = _totalSupply;
|
||||
balances[_creator] = _totalSupply;
|
||||
name = _name;
|
||||
symbol = _symbol;
|
||||
decimals = _decimals;
|
||||
}
|
||||
|
||||
function transfer(address to, uint256 amount) public returns (bool) {
|
||||
require(to != address(0), "TO_ADDRESS_IS_EMPTY");
|
||||
require(amount <= balances[msg.sender], "BALANCE_NOT_ENOUGH");
|
||||
|
||||
balances[msg.sender] = balances[msg.sender].sub(amount);
|
||||
balances[to] = balances[to].add(amount);
|
||||
emit Transfer(msg.sender, to, amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
function balanceOf(address owner) public view returns (uint256 balance) {
|
||||
return balances[owner];
|
||||
}
|
||||
|
||||
function transferFrom(
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
) public returns (bool) {
|
||||
require(to != address(0), "TO_ADDRESS_IS_EMPTY");
|
||||
require(amount <= balances[from], "BALANCE_NOT_ENOUGH");
|
||||
require(amount <= allowed[from][msg.sender], "ALLOWANCE_NOT_ENOUGH");
|
||||
|
||||
balances[from] = balances[from].sub(amount);
|
||||
balances[to] = balances[to].add(amount);
|
||||
allowed[from][msg.sender] = allowed[from][msg.sender].sub(amount);
|
||||
emit Transfer(from, to, amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
function approve(address spender, uint256 amount) public returns (bool) {
|
||||
allowed[msg.sender][spender] = amount;
|
||||
emit Approval(msg.sender, spender, amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
function allowance(address owner, address spender) public view returns (uint256) {
|
||||
return allowed[owner][spender];
|
||||
}
|
||||
}
|
||||
97
contracts/external/ERC20/InitializableMintableERC20.sol
vendored
Normal file
97
contracts/external/ERC20/InitializableMintableERC20.sol
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity 0.6.9;
|
||||
|
||||
import {SafeMath} from "../../lib/SafeMath.sol";
|
||||
import {InitializableOwnable} from "../../lib/InitializableOwnable.sol";
|
||||
|
||||
contract InitializableMintableERC20 is InitializableOwnable {
|
||||
using SafeMath for uint256;
|
||||
|
||||
string public name;
|
||||
uint256 public decimals;
|
||||
string public symbol;
|
||||
uint256 public totalSupply;
|
||||
|
||||
mapping(address => uint256) balances;
|
||||
mapping(address => mapping(address => uint256)) internal allowed;
|
||||
|
||||
event Transfer(address indexed from, address indexed to, uint256 amount);
|
||||
event Approval(address indexed owner, address indexed spender, uint256 amount);
|
||||
event Mint(address indexed user, uint256 value);
|
||||
event Burn(address indexed user, uint256 value);
|
||||
|
||||
function init(
|
||||
address _creator,
|
||||
uint256 _initSupply,
|
||||
string memory _name,
|
||||
string memory _symbol,
|
||||
uint256 _decimals
|
||||
) public {
|
||||
initOwner(_creator);
|
||||
name = _name;
|
||||
symbol = _symbol;
|
||||
decimals = _decimals;
|
||||
totalSupply = _initSupply;
|
||||
balances[_creator] = _initSupply;
|
||||
}
|
||||
|
||||
function transfer(address to, uint256 amount) public returns (bool) {
|
||||
require(to != address(0), "TO_ADDRESS_IS_EMPTY");
|
||||
require(amount <= balances[msg.sender], "BALANCE_NOT_ENOUGH");
|
||||
|
||||
balances[msg.sender] = balances[msg.sender].sub(amount);
|
||||
balances[to] = balances[to].add(amount);
|
||||
emit Transfer(msg.sender, to, amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
function balanceOf(address owner) public view returns (uint256 balance) {
|
||||
return balances[owner];
|
||||
}
|
||||
|
||||
function transferFrom(
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
) public returns (bool) {
|
||||
require(to != address(0), "TO_ADDRESS_IS_EMPTY");
|
||||
require(amount <= balances[from], "BALANCE_NOT_ENOUGH");
|
||||
require(amount <= allowed[from][msg.sender], "ALLOWANCE_NOT_ENOUGH");
|
||||
|
||||
balances[from] = balances[from].sub(amount);
|
||||
balances[to] = balances[to].add(amount);
|
||||
allowed[from][msg.sender] = allowed[from][msg.sender].sub(amount);
|
||||
emit Transfer(from, to, amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
function approve(address spender, uint256 amount) public returns (bool) {
|
||||
allowed[msg.sender][spender] = amount;
|
||||
emit Approval(msg.sender, spender, amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
function allowance(address owner, address spender) public view returns (uint256) {
|
||||
return allowed[owner][spender];
|
||||
}
|
||||
|
||||
function mint(address user, uint256 value) external onlyOwner {
|
||||
balances[user] = balances[user].add(value);
|
||||
totalSupply = totalSupply.add(value);
|
||||
emit Mint(user, value);
|
||||
emit Transfer(address(0), user, value);
|
||||
}
|
||||
|
||||
function burn(address user, uint256 value) external onlyOwner {
|
||||
balances[user] = balances[user].sub(value);
|
||||
totalSupply = totalSupply.sub(value);
|
||||
emit Burn(user, value);
|
||||
emit Transfer(user, address(0), value);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user