diff --git a/.gitignore b/.gitignore index 2d2b47d..0771856 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ -.idea -node_modules \ No newline at end of file +.idea/* +node_modules +build +contracts/flattened/*.sol +coverage +coverage.json \ No newline at end of file diff --git a/.idea/eth-bsc-swap-contracts.iml b/.idea/eth-bsc-swap-contracts.iml deleted file mode 100644 index c956989..0000000 --- a/.idea/eth-bsc-swap-contracts.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index d2f5058..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml deleted file mode 100644 index 4cf0d95..0000000 --- a/.idea/workspace.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..f33eca1 --- /dev/null +++ b/README.md @@ -0,0 +1,55 @@ +# ETH BSC Swap Contracts + +## Overview +ETH BSC Swap Contracts are responsible for registering swap pairs and swapping assets between ETH and BSC. + +![](./assets/eth-bsc-swap.png) + +### Register swap pair + +1. Users register swap pair for erc20 token on ETH via ETHSwapAgent(`createSwapPair`) if token is not registered. +2. Swap service will monitor the `SwapPairRegister` event and create swap pair on BSC: + + 1. create an BEP20 token on BSC + 2. record the relation between erc20 token and bep20 token. + +### Swap from ETH to BSC + +Once swap pair is registered, users can swap tokens from ETH to BSC. + +1. Users call `swapBSC2ETH` via ETHSwapAgent and specify erc20 token address, amount and swap fee. +2. Swap service will monitor the `SwapStarted` event and call `fillETH2BSCSwap` via BSCSwapAgent to mint corresponding bep20 +tokens to the same address that initiate the swap. + +### Swap from BSC to ETH + +Once swap pair is registered, users can swap tokens from BSC to ETH. + +1. Users call `swapBSC2ETH` via BSCSwapAgent and specify bep20 token address, amount and swap fee. Bep20 tokens will be burned. +2. Swap service will monitor the `SwapStarted` event and call `fillBSC2ETHSwap` via BSCSwapAgent to transfer corresponding erc20 + tokens to the same address that initiate the swap. + +## Generate contracts from templates + +```javascript +npm run generate +``` + +## Test + +Generate test contracts from templates: +```javascript +npm run generate-test +``` + +Run tests: + +```javascript +npm run truffle:test +``` + +Run coverage: + +```javascript +npm run coverage +``` diff --git a/assets/eth-bsc-swap.png b/assets/eth-bsc-swap.png new file mode 100644 index 0000000..57c1458 Binary files /dev/null and b/assets/eth-bsc-swap.png differ diff --git a/contracts/BSCSwapAgentImpl.sol b/contracts/BSCSwapAgentImpl.sol new file mode 100644 index 0000000..a709c96 --- /dev/null +++ b/contracts/BSCSwapAgentImpl.sol @@ -0,0 +1,137 @@ +pragma solidity 0.6.4; + +import "./interfaces/ISwap.sol"; +import "./bep20/BEP20UpgradeableProxy.sol"; +import './interfaces/IProxyInitialize.sol'; +import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol"; +import "openzeppelin-solidity/contracts/proxy/Initializable.sol"; +import "openzeppelin-solidity/contracts/GSN/Context.sol"; + +contract BSCSwapAgentImpl is Context, Initializable { + + + using SafeERC20 for IERC20; + + mapping(address => address) public swapMappingETH2BSC; + mapping(address => address) public swapMappingBSC2ETH; + mapping(bytes32 => bool) public filledETHTx; + + address payable public owner; + address public bep20ProxyAdmin; + address public bep20Implementation; + uint256 public swapFee; + + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + event SwapPairCreated(bytes32 indexed ethRegisterTxHash, address indexed bep20Addr, address indexed erc20Addr, string symbol, string name, uint8 decimals); + event SwapStarted(address indexed bep20Addr, address indexed erc20Addr, address indexed fromAddr, uint256 amount, uint256 feeAmount); + event SwapFilled(address indexed bep20Addr, bytes32 indexed ethTxHash, address indexed toAddress, uint256 amount); + + constructor() public { + } + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(owner == _msgSender(), "Ownable: caller is not the owner"); + _; + } + + modifier notContract() { + require(!isContract(msg.sender), "contract is not allowed to swap"); + require(msg.sender == tx.origin, "no proxy contract is allowed"); + _; + } + + + + function initialize(address bep20Impl, uint256 fee, address payable ownerAddr, address bep20ProxyAdminAddr) public initializer { + bep20Implementation = bep20Impl; + swapFee = fee; + owner = ownerAddr; + bep20ProxyAdmin = bep20ProxyAdminAddr; + } + + function isContract(address addr) internal view returns (bool) { + uint size; + assembly { size := extcodesize(addr) } + return size > 0; + } + + /** + * @dev Leaves the contract without owner. It will not be possible to call + * `onlyOwner` functions anymore. Can only be called by the current owner. + * + * NOTE: Renouncing ownership will leave the contract without an owner, + * thereby removing any functionality that is only available to the owner. + */ + function renounceOwnership() public onlyOwner { + emit OwnershipTransferred(owner, address(0)); + owner = address(0); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + * Can only be called by the current owner. + */ + function transferOwnership(address payable newOwner) public onlyOwner { + require(newOwner != address(0), "Ownable: new owner is the zero address"); + emit OwnershipTransferred(owner, newOwner); + owner = newOwner; + } + + /** + * @dev Returns set minimum swap fee from BEP20 to ERC20 + */ + function setSwapFee(uint256 fee) onlyOwner external { + swapFee = fee; + } + + /** + * @dev createSwapPair + */ + function createSwapPair(bytes32 ethTxHash, address erc20Addr, string calldata name, string calldata symbol, uint8 decimals) onlyOwner external returns (address) { + require(swapMappingETH2BSC[erc20Addr] == address(0x0), "duplicated swap pair"); + + BEP20UpgradeableProxy proxyToken = new BEP20UpgradeableProxy(bep20Implementation, bep20ProxyAdmin, ""); + IProxyInitialize token = IProxyInitialize(address(proxyToken)); + token.initialize(name, symbol, decimals, 0, true, address(this)); + + swapMappingETH2BSC[erc20Addr] = address(token); + swapMappingBSC2ETH[address(token)] = erc20Addr; + + emit SwapPairCreated(ethTxHash, address(token), erc20Addr, symbol, name, decimals); + return address(token); + } + + /** + * @dev fillETH2BSCSwap + */ + function fillETH2BSCSwap(bytes32 ethTxHash, address erc20Addr, address toAddress, uint256 amount) onlyOwner external returns (bool) { + require(!filledETHTx[ethTxHash], "eth tx filled already"); + address bscTokenAddr = swapMappingETH2BSC[erc20Addr]; + require(bscTokenAddr != address(0x0), "no swap pair for this token"); + filledETHTx[ethTxHash] = true; + ISwap(bscTokenAddr).mintTo(amount, toAddress); + emit SwapFilled(bscTokenAddr, ethTxHash, toAddress, amount); + + return true; + } + /** + * @dev swapBSC2ETH + */ + function swapBSC2ETH(address bep20Addr, uint256 amount) payable external notContract returns (bool) { + address erc20Addr = swapMappingBSC2ETH[bep20Addr]; + require(erc20Addr != address(0x0), "no swap pair for this token"); + require(msg.value == swapFee, "swap fee not equal"); + + IERC20(bep20Addr).safeTransferFrom(msg.sender, address(this), amount); + ISwap(bep20Addr).burn(amount); + if (msg.value != 0) { + owner.transfer(msg.value); + } + + emit SwapStarted(bep20Addr, erc20Addr, msg.sender, amount, msg.value); + return true; + } +} \ No newline at end of file diff --git a/contracts/BSCSwapAgentImpl.template b/contracts/BSCSwapAgentImpl.template new file mode 100644 index 0000000..7892165 --- /dev/null +++ b/contracts/BSCSwapAgentImpl.template @@ -0,0 +1,147 @@ +pragma solidity 0.6.4; + +import "./interfaces/ISwap.sol"; +import "./bep20/BEP20UpgradeableProxy.sol"; +import './interfaces/IProxyInitialize.sol'; +import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol"; +{% if mock %}{% else %}import "openzeppelin-solidity/contracts/proxy/Initializable.sol";{% endif %} +import "openzeppelin-solidity/contracts/GSN/Context.sol"; +{% if mock %} +contract BSCSwapAgentImpl is Context { +{% else %} +contract BSCSwapAgentImpl is Context, Initializable { +{% endif %} + + using SafeERC20 for IERC20; + + mapping(address => address) public swapMappingETH2BSC; + mapping(address => address) public swapMappingBSC2ETH; + mapping(bytes32 => bool) public filledETHTx; + + address payable public owner; + address public bep20ProxyAdmin; + address public bep20Implementation; + uint256 public swapFee; + + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + event SwapPairCreated(bytes32 indexed ethRegisterTxHash, address indexed bep20Addr, address indexed erc20Addr, string symbol, string name, uint8 decimals); + event SwapStarted(address indexed bep20Addr, address indexed erc20Addr, address indexed fromAddr, uint256 amount, uint256 feeAmount); + event SwapFilled(address indexed bep20Addr, bytes32 indexed ethTxHash, address indexed toAddress, uint256 amount); +{% if mock %} + constructor(address bep20Impl, uint256 fee, address bep20ProxyAdminAddr) public { + bep20Implementation = bep20Impl; + swapFee = fee; + owner = _msgSender(); + bep20ProxyAdmin = bep20ProxyAdminAddr; + } +{% else %} + constructor() public { + } +{% endif %} + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(owner == _msgSender(), "Ownable: caller is not the owner"); + _; + } + + modifier notContract() { + require(!isContract(msg.sender), "contract is not allowed to swap"); + require(msg.sender == tx.origin, "no proxy contract is allowed"); + _; + } + + +{% if mock %} +{% else %} + function initialize(address bep20Impl, uint256 fee, address payable ownerAddr, address bep20ProxyAdminAddr) public initializer { + bep20Implementation = bep20Impl; + swapFee = fee; + owner = ownerAddr; + bep20ProxyAdmin = bep20ProxyAdminAddr; + } +{% endif %} + function isContract(address addr) internal view returns (bool) { + uint size; + assembly { size := extcodesize(addr) } + return size > 0; + } + + /** + * @dev Leaves the contract without owner. It will not be possible to call + * `onlyOwner` functions anymore. Can only be called by the current owner. + * + * NOTE: Renouncing ownership will leave the contract without an owner, + * thereby removing any functionality that is only available to the owner. + */ + function renounceOwnership() public onlyOwner { + emit OwnershipTransferred(owner, address(0)); + owner = address(0); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + * Can only be called by the current owner. + */ + function transferOwnership(address payable newOwner) public onlyOwner { + require(newOwner != address(0), "Ownable: new owner is the zero address"); + emit OwnershipTransferred(owner, newOwner); + owner = newOwner; + } + + /** + * @dev Returns set minimum swap fee from BEP20 to ERC20 + */ + function setSwapFee(uint256 fee) onlyOwner external { + swapFee = fee; + } + + /** + * @dev createSwapPair + */ + function createSwapPair(bytes32 ethTxHash, address erc20Addr, string calldata name, string calldata symbol, uint8 decimals) onlyOwner external returns (address) { + require(swapMappingETH2BSC[erc20Addr] == address(0x0), "duplicated swap pair"); + + BEP20UpgradeableProxy proxyToken = new BEP20UpgradeableProxy(bep20Implementation, bep20ProxyAdmin, ""); + IProxyInitialize token = IProxyInitialize(address(proxyToken)); + token.initialize(name, symbol, decimals, 0, true, address(this)); + + swapMappingETH2BSC[erc20Addr] = address(token); + swapMappingBSC2ETH[address(token)] = erc20Addr; + + emit SwapPairCreated(ethTxHash, address(token), erc20Addr, symbol, name, decimals); + return address(token); + } + + /** + * @dev fillETH2BSCSwap + */ + function fillETH2BSCSwap(bytes32 ethTxHash, address erc20Addr, address toAddress, uint256 amount) onlyOwner external returns (bool) { + require(!filledETHTx[ethTxHash], "eth tx filled already"); + address bscTokenAddr = swapMappingETH2BSC[erc20Addr]; + require(bscTokenAddr != address(0x0), "no swap pair for this token"); + filledETHTx[ethTxHash] = true; + ISwap(bscTokenAddr).mintTo(amount, toAddress); + emit SwapFilled(bscTokenAddr, ethTxHash, toAddress, amount); + + return true; + } + /** + * @dev swapBSC2ETH + */ + function swapBSC2ETH(address bep20Addr, uint256 amount) payable external notContract returns (bool) { + address erc20Addr = swapMappingBSC2ETH[bep20Addr]; + require(erc20Addr != address(0x0), "no swap pair for this token"); + require(msg.value == swapFee, "swap fee not equal"); + + IERC20(bep20Addr).safeTransferFrom(msg.sender, address(this), amount); + ISwap(bep20Addr).burn(amount); + if (msg.value != 0) { + owner.transfer(msg.value); + } + + emit SwapStarted(bep20Addr, erc20Addr, msg.sender, amount, msg.value); + return true; + } +} \ No newline at end of file diff --git a/contracts/BSCSwapAgentUpgradeableProxy.sol b/contracts/BSCSwapAgentUpgradeableProxy.sol new file mode 100644 index 0000000..31b7364 --- /dev/null +++ b/contracts/BSCSwapAgentUpgradeableProxy.sol @@ -0,0 +1,11 @@ +pragma solidity ^0.6.0; + +import "openzeppelin-solidity/contracts/proxy/TransparentUpgradeableProxy.sol"; + +contract BSCSwapAgentUpgradeableProxy is TransparentUpgradeableProxy { + + constructor(address logic, address admin, bytes memory data) TransparentUpgradeableProxy(logic, admin, data) public { + + } + +} \ No newline at end of file diff --git a/contracts/ETHSwapAgentImpl.sol b/contracts/ETHSwapAgentImpl.sol new file mode 100644 index 0000000..af02c9d --- /dev/null +++ b/contracts/ETHSwapAgentImpl.sol @@ -0,0 +1,118 @@ +pragma solidity 0.6.4; + +import "./interfaces/IERC20Query.sol"; +import "openzeppelin-solidity/contracts/proxy/Initializable.sol"; +import "openzeppelin-solidity/contracts/GSN/Context.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol"; + +contract ETHSwapAgentImpl is Context, Initializable { + + using SafeERC20 for IERC20; + + mapping(address => bool) public registeredERC20; + mapping(bytes32 => bool) public filledBSCTx; + address payable public owner; + uint256 public swapFee; + + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + event SwapPairRegister(address indexed sponsor,address indexed erc20Addr, string name, string symbol, uint8 decimals); + event SwapStarted(address indexed erc20Addr, address indexed fromAddr, uint256 amount, uint256 feeAmount); + event SwapFilled(address indexed erc20Addr, bytes32 indexed bscTxHash, address indexed toAddress, uint256 amount); + + constructor() public { + } + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(owner == _msgSender(), "Ownable: caller is not the owner"); + _; + } + + function initialize(uint256 fee, address payable ownerAddr) public initializer { + swapFee = fee; + owner = ownerAddr; + } + + modifier notContract() { + require(!isContract(msg.sender), "contract is not allowed to swap"); + require(msg.sender == tx.origin, "no proxy contract is allowed"); + _; + } + + function isContract(address addr) internal view returns (bool) { + uint size; + assembly { size := extcodesize(addr) } + return size > 0; + } + + /** + * @dev Leaves the contract without owner. It will not be possible to call + * `onlyOwner` functions anymore. Can only be called by the current owner. + * + * NOTE: Renouncing ownership will leave the contract without an owner, + * thereby removing any functionality that is only available to the owner. + */ + function renounceOwnership() public onlyOwner { + emit OwnershipTransferred(owner, address(0)); + owner = address(0); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + * Can only be called by the current owner. + */ + function transferOwnership(address payable newOwner) public onlyOwner { + require(newOwner != address(0), "Ownable: new owner is the zero address"); + emit OwnershipTransferred(owner, newOwner); + owner = newOwner; + } + + /** + * @dev Returns set minimum swap fee from ERC20 to BEP20 + */ + function setSwapFee(uint256 fee) onlyOwner external { + swapFee = fee; + } + + function registerSwapPairToBSC(address erc20Addr) external returns (bool) { + require(!registeredERC20[erc20Addr], "already registered"); + + string memory name = IERC20Query(erc20Addr).name(); + string memory symbol = IERC20Query(erc20Addr).symbol(); + uint8 decimals = IERC20Query(erc20Addr).decimals(); + + require(bytes(name).length>0, "empty name"); + require(bytes(symbol).length>0, "empty symbol"); + + registeredERC20[erc20Addr] = true; + + emit SwapPairRegister(msg.sender, erc20Addr, name, symbol, decimals); + return true; + } + + function fillBSC2ETHSwap(bytes32 bscTxHash, address erc20Addr, address toAddress, uint256 amount) onlyOwner external returns (bool) { + require(!filledBSCTx[bscTxHash], "bsc tx filled already"); + require(registeredERC20[erc20Addr], "not registered token"); + + filledBSCTx[bscTxHash] = true; + IERC20(erc20Addr).safeTransfer(toAddress, amount); + + emit SwapFilled(erc20Addr, bscTxHash, toAddress, amount); + return true; + } + + function swapETH2BSC(address erc20Addr, uint256 amount) payable external notContract returns (bool) { + require(registeredERC20[erc20Addr], "not registered token"); + require(msg.value == swapFee, "swap fee not equal"); + + IERC20(erc20Addr).safeTransferFrom(msg.sender, address(this), amount); + if (msg.value != 0) { + owner.transfer(msg.value); + } + + emit SwapStarted(erc20Addr, msg.sender, amount, msg.value); + return true; + } +} \ No newline at end of file diff --git a/contracts/ETHSwapAgentImpl.template b/contracts/ETHSwapAgentImpl.template new file mode 100644 index 0000000..cd9ea61 --- /dev/null +++ b/contracts/ETHSwapAgentImpl.template @@ -0,0 +1,125 @@ +pragma solidity 0.6.4; + +import "./interfaces/IERC20Query.sol"; +{% if mock %}{% else %}import "openzeppelin-solidity/contracts/proxy/Initializable.sol";{% endif %} +import "openzeppelin-solidity/contracts/GSN/Context.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol"; +{% if mock %} +contract ETHSwapAgentImpl is Context { +{% else %} +contract ETHSwapAgentImpl is Context, Initializable { +{% endif %} + using SafeERC20 for IERC20; + + mapping(address => bool) public registeredERC20; + mapping(bytes32 => bool) public filledBSCTx; + address payable public owner; + uint256 public swapFee; + + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + event SwapPairRegister(address indexed sponsor,address indexed erc20Addr, string name, string symbol, uint8 decimals); + event SwapStarted(address indexed erc20Addr, address indexed fromAddr, uint256 amount, uint256 feeAmount); + event SwapFilled(address indexed erc20Addr, bytes32 indexed bscTxHash, address indexed toAddress, uint256 amount); +{% if mock %} + constructor(uint256 fee) public { + swapFee = fee; + owner = _msgSender(); + } +{% else %} + constructor() public { + } +{% endif %} + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(owner == _msgSender(), "Ownable: caller is not the owner"); + _; + } +{% if mock %}{% else %} + function initialize(uint256 fee, address payable ownerAddr) public initializer { + swapFee = fee; + owner = ownerAddr; + } +{% endif %} + modifier notContract() { + require(!isContract(msg.sender), "contract is not allowed to swap"); + require(msg.sender == tx.origin, "no proxy contract is allowed"); + _; + } + + function isContract(address addr) internal view returns (bool) { + uint size; + assembly { size := extcodesize(addr) } + return size > 0; + } + + /** + * @dev Leaves the contract without owner. It will not be possible to call + * `onlyOwner` functions anymore. Can only be called by the current owner. + * + * NOTE: Renouncing ownership will leave the contract without an owner, + * thereby removing any functionality that is only available to the owner. + */ + function renounceOwnership() public onlyOwner { + emit OwnershipTransferred(owner, address(0)); + owner = address(0); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + * Can only be called by the current owner. + */ + function transferOwnership(address payable newOwner) public onlyOwner { + require(newOwner != address(0), "Ownable: new owner is the zero address"); + emit OwnershipTransferred(owner, newOwner); + owner = newOwner; + } + + /** + * @dev Returns set minimum swap fee from ERC20 to BEP20 + */ + function setSwapFee(uint256 fee) onlyOwner external { + swapFee = fee; + } + + function registerSwapPairToBSC(address erc20Addr) external returns (bool) { + require(!registeredERC20[erc20Addr], "already registered"); + + string memory name = IERC20Query(erc20Addr).name(); + string memory symbol = IERC20Query(erc20Addr).symbol(); + uint8 decimals = IERC20Query(erc20Addr).decimals(); + + require(bytes(name).length>0, "empty name"); + require(bytes(symbol).length>0, "empty symbol"); + + registeredERC20[erc20Addr] = true; + + emit SwapPairRegister(msg.sender, erc20Addr, name, symbol, decimals); + return true; + } + + function fillBSC2ETHSwap(bytes32 bscTxHash, address erc20Addr, address toAddress, uint256 amount) onlyOwner external returns (bool) { + require(!filledBSCTx[bscTxHash], "bsc tx filled already"); + require(registeredERC20[erc20Addr], "not registered token"); + + filledBSCTx[bscTxHash] = true; + IERC20(erc20Addr).safeTransfer(toAddress, amount); + + emit SwapFilled(erc20Addr, bscTxHash, toAddress, amount); + return true; + } + + function swapETH2BSC(address erc20Addr, uint256 amount) payable external notContract returns (bool) { + require(registeredERC20[erc20Addr], "not registered token"); + require(msg.value == swapFee, "swap fee not equal"); + + IERC20(erc20Addr).safeTransferFrom(msg.sender, address(this), amount); + if (msg.value != 0) { + owner.transfer(msg.value); + } + + emit SwapStarted(erc20Addr, msg.sender, amount, msg.value); + return true; + } +} \ No newline at end of file diff --git a/contracts/ETHSwapAgentUpgradeableProxy.sol b/contracts/ETHSwapAgentUpgradeableProxy.sol new file mode 100644 index 0000000..f4b00af --- /dev/null +++ b/contracts/ETHSwapAgentUpgradeableProxy.sol @@ -0,0 +1,11 @@ +pragma solidity ^0.6.0; + +import "openzeppelin-solidity/contracts/proxy/TransparentUpgradeableProxy.sol"; + +contract ETHSwapAgentUpgradeableProxy is TransparentUpgradeableProxy { + + constructor(address logic, address admin, bytes memory data) TransparentUpgradeableProxy(logic, admin, data) public { + + } + +} \ No newline at end of file diff --git a/contracts/SwapProxy.sol b/contracts/SwapProxy.sol deleted file mode 100644 index d9fdca8..0000000 --- a/contracts/SwapProxy.sol +++ /dev/null @@ -1,34 +0,0 @@ -pragma solidity 0.6.4; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; - -contract SwapProxy is Ownable { - uint256 public swapFee; - address payable public relayer; - - event tokenTransfer(address indexed contractAddr, address indexed fromAddr, address indexed toAddr, uint256 amount, uint256 feeAmount); - - constructor (address payable relayerAddr, uint256 fee) public { - relayer = relayerAddr; - swapFee = fee; - } - - function close() public onlyOwner { - address payable ownerAddr = payable(owner()); - selfdestruct(ownerAddr); - } - - function swap(address contractAddr, uint256 amount) payable external returns (bool) { - require(msg.value >= swapFee, "fee amount should not be less than the amount of swapFee"); - require(amount > 0, "amount should be larger than 0"); - - relayer.transfer(msg.value); - - bool success = IERC20(contractAddr).transferFrom(msg.sender, relayer, amount); - require(success, "transfer token failed"); - - emit tokenTransfer(contractAddr, msg.sender, relayer, amount, msg.value); - return true; - } -} diff --git a/contracts/bep20/BEP20TokenImplementation.sol b/contracts/bep20/BEP20TokenImplementation.sol new file mode 100644 index 0000000..64a1132 --- /dev/null +++ b/contracts/bep20/BEP20TokenImplementation.sol @@ -0,0 +1,333 @@ +pragma solidity 0.6.4; + +import "../interfaces/IBEP20.sol"; +import "../interfaces/ISwap.sol"; +import "openzeppelin-solidity/contracts/GSN/Context.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "openzeppelin-solidity/contracts/proxy/Initializable.sol"; + +contract BEP20TokenImplementation is Context, IBEP20, ISwap, Initializable { + using SafeMath for uint256; + + mapping (address => uint256) private _balances; + mapping (address => mapping (address => uint256)) private _allowances; + uint256 private _totalSupply; + string private _name; + string private _symbol; + uint8 private _decimals; + + address private _owner; + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + bool private _mintable; + + constructor() public { + } + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(_owner == _msgSender(), "Ownable: caller is not the owner"); + _; + } + + /** + * @dev sets initials supply and the owner + */ + function initialize(string memory name, string memory symbol, uint8 decimals, uint256 amount, bool mintable, address owner) public initializer { + _owner = owner; + _name = name; + _symbol = symbol; + _decimals = decimals; + _mintable = mintable; + _mint(owner, amount); + } + + /** + * @dev Leaves the contract without owner. It will not be possible to call + * `onlyOwner` functions anymore. Can only be called by the current owner. + * + * NOTE: Renouncing ownership will leave the contract without an owner, + * thereby removing any functionality that is only available to the owner. + */ + function renounceOwnership() public onlyOwner { + emit OwnershipTransferred(_owner, address(0)); + _owner = address(0); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + * Can only be called by the current owner. + */ + function transferOwnership(address newOwner) public onlyOwner { + require(newOwner != address(0), "Ownable: new owner is the zero address"); + emit OwnershipTransferred(_owner, newOwner); + _owner = newOwner; + } + + /** + * @dev Returns if the token is mintable or not + */ + function mintable() external view returns (bool) { + return _mintable; + } + + /** + * @dev Returns the bep token owner. + */ + function getOwner() external override view returns (address) { + return _owner; + } + + /** + * @dev Returns the token decimals. + */ + function decimals() external override view returns (uint8) { + return _decimals; + } + + /** + * @dev Returns the token symbol. + */ + function symbol() external override view returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the token name. + */ + function name() external override view returns (string memory) { + return _name; + } + + /** + * @dev See {BEP20-totalSupply}. + */ + function totalSupply() external override view returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {BEP20-balanceOf}. + */ + function balanceOf(address account) external override view returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {BEP20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) external override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {BEP20-allowance}. + */ + function allowance(address owner, address spender) external override view returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {BEP20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) external override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {BEP20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {BEP20}; + * + * Requirements: + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for `sender`'s tokens of at least + * `amount`. + */ + function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) { + _transfer(sender, recipient, amount); + _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "BEP20: transfer amount exceeds allowance")); + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {BEP20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {BEP20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "BEP20: decreased allowance below zero")); + return true; + } + + /** + * @dev Creates `amount` tokens and assigns them to `msg.sender`, increasing + * the total supply. + * + * Requirements + * + * - `msg.sender` must be the token owner + * - `_mintable` must be true + */ + function mint(uint256 amount) public onlyOwner returns (bool) { + require(_mintable, "this token is not mintable"); + _mint(_msgSender(), amount); + return true; + } + + /** + * @dev Creates `amount` tokens and assigns them to `recipient`, increasing + * the total supply. + * + * Requirements + * + * - `msg.sender` must be the token owner + * - `_mintable` must be true + */ + function mintTo(uint256 amount, address recipient) override external onlyOwner returns (bool) { + require(_mintable, "this token is not mintable"); + _mint(recipient, amount); + return true; + } + + + /** + * @dev Burn `amount` tokens and decreasing the total supply. + */ + function burn(uint256 amount) override external returns (bool) { + _burn(_msgSender(), amount); + return true; + } + + /** + * @dev Moves tokens `amount` from `sender` to `recipient`. + * + * This is internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer(address sender, address recipient, uint256 amount) internal { + require(sender != address(0), "BEP20: transfer from the zero address"); + require(recipient != address(0), "BEP20: transfer to the zero address"); + + _balances[sender] = _balances[sender].sub(amount, "BEP20: transfer amount exceeds balance"); + _balances[recipient] = _balances[recipient].add(amount); + emit Transfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements + * + * - `to` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal { + require(account != address(0), "BEP20: mint to the zero address"); + + _totalSupply = _totalSupply.add(amount); + _balances[account] = _balances[account].add(amount); + emit Transfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal { + require(account != address(0), "BEP20: burn from the zero address"); + + _balances[account] = _balances[account].sub(amount, "BEP20: burn amount exceeds balance"); + _totalSupply = _totalSupply.sub(amount); + emit Transfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. + * + * This is 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. + */ + function _approve(address owner, address spender, uint256 amount) internal { + require(owner != address(0), "BEP20: approve from the zero address"); + require(spender != address(0), "BEP20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`.`amount` is then deducted + * from the caller's allowance. + * + * See {_burn} and {_approve}. + */ + function _burnFrom(address account, uint256 amount) internal { + _burn(account, amount); + _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "BEP20: burn amount exceeds allowance")); + } +} \ No newline at end of file diff --git a/contracts/bep20/BEP20UpgradeableProxy.sol b/contracts/bep20/BEP20UpgradeableProxy.sol new file mode 100644 index 0000000..a67ccb1 --- /dev/null +++ b/contracts/bep20/BEP20UpgradeableProxy.sol @@ -0,0 +1,11 @@ +pragma solidity 0.6.4; + +import "openzeppelin-solidity/contracts/proxy/TransparentUpgradeableProxy.sol"; + +contract BEP20UpgradeableProxy is TransparentUpgradeableProxy { + + constructor(address logic, address admin, bytes memory data) TransparentUpgradeableProxy(logic, admin, data) public { + + } + +} \ No newline at end of file diff --git a/contracts/flattened/.gitkeep b/contracts/flattened/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/contracts/flattened/SwapProxy.sol b/contracts/flattened/SwapProxy.sol deleted file mode 100644 index c5890d6..0000000 --- a/contracts/flattened/SwapProxy.sol +++ /dev/null @@ -1,213 +0,0 @@ - -// File: @openzeppelin/contracts/token/ERC20/IERC20.sol - -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.0; - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `recipient`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address recipient, uint256 amount) 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 `amount` 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 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `sender` to `recipient` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); - - /** - * @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); -} - -// File: @openzeppelin/contracts/GSN/Context.sol - -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.0; - -/* - * @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 GSN 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 payable) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes memory) { - this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 - return msg.data; - } -} - -// File: @openzeppelin/contracts/access/Ownable.sol - -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.0; - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor () internal { - address msgSender = _msgSender(); - _owner = msgSender; - emit OwnershipTransferred(address(0), msgSender); - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view returns (address) { - return _owner; - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(_owner == _msgSender(), "Ownable: caller is not the owner"); - _; - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - emit OwnershipTransferred(_owner, address(0)); - _owner = address(0); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - emit OwnershipTransferred(_owner, newOwner); - _owner = newOwner; - } -} - -// File: contracts/SwapProxy.sol - -pragma solidity 0.6.4; - - - -contract SwapProxy is Ownable { - uint256 public swapFee; - address payable public relayer; - - event tokenTransfer(address indexed contractAddr, address indexed fromAddr, address indexed toAddr, uint256 amount, uint256 feeAmount); - - constructor (address payable relayerAddr, uint256 fee) public { - relayer = relayerAddr; - swapFee = fee; - } - - function close() public onlyOwner { - address payable ownerAddr = payable(owner()); - selfdestruct(ownerAddr); - } - - function swap(address contractAddr, uint256 amount) payable external returns (bool) { - require(msg.value >= swapFee, "fee amount should not be less than the amount of swapFee"); - require(amount > 0, "amount should be larger than 0"); - - relayer.transfer(msg.value); - - bool success = IERC20(contractAddr).transferFrom(msg.sender, relayer, amount); - require(success, "transfer token failed"); - - emit tokenTransfer(contractAddr, msg.sender, relayer, amount, msg.value); - return true; - } -} diff --git a/contracts/interfaces/IBEP20.sol b/contracts/interfaces/IBEP20.sol new file mode 100644 index 0000000..d9c6605 --- /dev/null +++ b/contracts/interfaces/IBEP20.sol @@ -0,0 +1,92 @@ +pragma solidity 0.6.4; + +interface IBEP20 { + /** + * @dev Returns the amount of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the token decimals. + */ + function decimals() external view returns (uint8); + + /** + * @dev Returns the token symbol. + */ + function symbol() external view returns (string memory); + + /** + * @dev Returns the token name. + */ + function name() external view returns (string memory); + + /** + * @dev Returns the bep token owner. + */ + function getOwner() external view returns (address); + + /** + * @dev Returns the amount of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Moves `amount` tokens from the caller's account to `recipient`. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transfer(address recipient, uint256 amount) 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 `amount` 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 amount) external returns (bool); + + /** + * @dev Moves `amount` tokens from `sender` to `recipient` using the + * allowance mechanism. `amount` is then deducted from the caller's + * allowance. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); + + /** + * @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); +} diff --git a/contracts/interfaces/IERC20Query.sol b/contracts/interfaces/IERC20Query.sol new file mode 100644 index 0000000..a53ba25 --- /dev/null +++ b/contracts/interfaces/IERC20Query.sol @@ -0,0 +1,28 @@ +pragma solidity 0.6.4; + +interface IERC20Query { + /** + * @dev Returns the amount of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the token decimals. + */ + function decimals() external view returns (uint8); + + /** + * @dev Returns the token symbol. + */ + function symbol() external view returns (string memory); + + /** + * @dev Returns the token name. + */ + function name() external view returns (string memory); + + /** + * @dev Returns the amount of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); +} diff --git a/contracts/interfaces/IProxyInitialize.sol b/contracts/interfaces/IProxyInitialize.sol new file mode 100644 index 0000000..b303ea0 --- /dev/null +++ b/contracts/interfaces/IProxyInitialize.sol @@ -0,0 +1,5 @@ +pragma solidity 0.6.4; + +interface IProxyInitialize { + function initialize(string calldata name, string calldata symbol, uint8 decimals, uint256 amount, bool mintable, address owner) external; +} \ No newline at end of file diff --git a/contracts/interfaces/ISwap.sol b/contracts/interfaces/ISwap.sol new file mode 100644 index 0000000..f5a6db3 --- /dev/null +++ b/contracts/interfaces/ISwap.sol @@ -0,0 +1,19 @@ +pragma solidity 0.6.4; + +interface ISwap { + /** + * @dev Creates `amount` tokens and assigns them to `recipient`, increasing + * the total supply. + * + * Requirements + * + * - `msg.sender` must be the token owner + * - `_mintable` must be true + */ + function mintTo(uint256 amount, address recipient) external returns (bool); + + /** + * @dev Burn `amount` tokens and decreasing the total supply. + */ + function burn(uint256 amount) external returns (bool); +} diff --git a/contracts/test/ERC20ABC.sol b/contracts/test/ERC20ABC.sol new file mode 100644 index 0000000..68967d6 --- /dev/null +++ b/contracts/test/ERC20ABC.sol @@ -0,0 +1,602 @@ + +// File: contracts/interface/IBEP20.sol + +pragma solidity 0.6.4; + +interface IBEP20 { + /** + * @dev Returns the amount of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the token decimals. + */ + function decimals() external view returns (uint8); + + /** + * @dev Returns the token symbol. + */ + function symbol() external view returns (string memory); + + /** + * @dev Returns the token name. + */ + function name() external view returns (string memory); + + /** + * @dev Returns the bep token owner. + */ + function getOwner() external view returns (address); + + /** + * @dev Returns the amount of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Moves `amount` tokens from the caller's account to `recipient`. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transfer(address recipient, uint256 amount) 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 `amount` 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 amount) external returns (bool); + + /** + * @dev Moves `amount` tokens from `sender` to `recipient` using the + * allowance mechanism. `amount` is then deducted from the caller's + * allowance. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); + + /** + * @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); +} + +// File: openzeppelin-solidity/contracts/GSN/Context.sol + +pragma solidity ^0.6.0; + +/* + * @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 GSN 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. + */ +contract Context { + // Empty internal constructor, to prevent people from mistakenly deploying + // an instance of this contract, which should be used via inheritance. + constructor () internal { } + + function _msgSender() internal view virtual returns (address payable) { + return msg.sender; + } + + function _msgData() internal view virtual returns (bytes memory) { + this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 + return msg.data; + } +} + +// File: openzeppelin-solidity/contracts/math/SafeMath.sol + +pragma solidity ^0.6.0; + +/** + * @dev Wrappers over Solidity's arithmetic operations with added overflow + * checks. + * + * Arithmetic operations in Solidity wrap on overflow. This can easily result + * in bugs, because programmers usually assume that an overflow raises an + * error, which is the standard behavior in high level programming languages. + * `SafeMath` restores this intuition by reverting the transaction when an + * operation overflows. + * + * Using this library instead of the unchecked operations eliminates an entire + * class of bugs, so it's recommended to use it always. + */ +library SafeMath { + /** + * @dev Returns the addition of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `+` operator. + * + * Requirements: + * - Addition cannot overflow. + */ + function add(uint256 a, uint256 b) internal pure returns (uint256) { + uint256 c = a + b; + require(c >= a, "SafeMath: addition overflow"); + + return c; + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * - Subtraction cannot overflow. + */ + function sub(uint256 a, uint256 b) internal pure returns (uint256) { + return sub(a, b, "SafeMath: subtraction overflow"); + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting with custom message on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * - Subtraction cannot overflow. + */ + function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b <= a, errorMessage); + uint256 c = a - b; + + return c; + } + + /** + * @dev Returns the multiplication of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `*` operator. + * + * Requirements: + * - Multiplication cannot overflow. + */ + function mul(uint256 a, uint256 b) internal pure returns (uint256) { + // Gas optimization: this is cheaper than requiring 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 + if (a == 0) { + return 0; + } + + uint256 c = a * b; + require(c / a == b, "SafeMath: multiplication overflow"); + + return c; + } + + /** + * @dev Returns the integer division of two unsigned integers. Reverts on + * division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b) internal pure returns (uint256) { + return div(a, b, "SafeMath: division by zero"); + } + + /** + * @dev Returns the integer division of two unsigned integers. Reverts with custom message on + * division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + // Solidity only automatically asserts when dividing by 0 + require(b > 0, errorMessage); + uint256 c = a / b; + // assert(a == b * c + a % b); // There is no case in which this doesn't hold + + return c; + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * Reverts when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b) internal pure returns (uint256) { + return mod(a, b, "SafeMath: modulo by zero"); + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * Reverts with custom message when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b != 0, errorMessage); + return a % b; + } +} + +// File: openzeppelin-solidity/contracts/access/Ownable.sol + +pragma solidity ^0.6.0; + +/** + * @dev Contract module which provides a basic access control mechanism, where + * there is an account (an owner) that can be granted exclusive access to + * specific functions. + * + * By default, the owner account will be the one that deploys the contract. This + * can later be changed with {transferOwnership}. + * + * This module is used through inheritance. It will make available the modifier + * `onlyOwner`, which can be applied to your functions to restrict their use to + * the owner. + */ +contract Ownable is Context { + address private _owner; + + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + /** + * @dev Initializes the contract setting the deployer as the initial owner. + */ + constructor () internal { + address msgSender = _msgSender(); + _owner = msgSender; + emit OwnershipTransferred(address(0), msgSender); + } + + /** + * @dev Returns the address of the current owner. + */ + function owner() public view returns (address) { + return _owner; + } + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(_owner == _msgSender(), "Ownable: caller is not the owner"); + _; + } + + /** + * @dev Leaves the contract without owner. It will not be possible to call + * `onlyOwner` functions anymore. Can only be called by the current owner. + * + * NOTE: Renouncing ownership will leave the contract without an owner, + * thereby removing any functionality that is only available to the owner. + */ + function renounceOwnership() public virtual onlyOwner { + emit OwnershipTransferred(_owner, address(0)); + _owner = address(0); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + * Can only be called by the current owner. + */ + function transferOwnership(address newOwner) public virtual onlyOwner { + _transferOwnership(newOwner); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + */ + function _transferOwnership(address newOwner) internal virtual { + require(newOwner != address(0), "Ownable: new owner is the zero address"); + emit OwnershipTransferred(_owner, newOwner); + _owner = newOwner; + } +} + +// File: contracts/test/ABCToken.sol + +pragma solidity 0.6.4; + + + + + +contract ERC20ABC is Context, IBEP20, Ownable { + using SafeMath for uint256; + + mapping (address => uint256) private _balances; + + mapping (address => mapping (address => uint256)) private _allowances; + + uint256 private _totalSupply; + uint8 public _decimals; + string public _symbol; + string public _name; + + constructor() public { + _name = "ABC token"; + _symbol = "ABC"; + _decimals = 18; + _totalSupply = 100000000000000000000000000; + _balances[msg.sender] = _totalSupply; + + emit Transfer(address(0), msg.sender, _totalSupply); + } + + /** + * @dev Returns the bep token owner. + */ + function getOwner() external override view returns (address) { + return owner(); + } + + /** + * @dev Returns the token decimals. + */ + function decimals() external override view returns (uint8) { + return _decimals; + } + + /** + * @dev Returns the token symbol. + */ + function symbol() external override view returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the token name. + */ + function name() external override view returns (string memory) { + return _name; + } + + /** + * @dev See {BEP20-totalSupply}. + */ + function totalSupply() external override view returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {BEP20-balanceOf}. + */ + function balanceOf(address account) external override view returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {BEP20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) external override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {BEP20-allowance}. + */ + function allowance(address owner, address spender) external override view returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {BEP20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) external override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {BEP20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {BEP20}; + * + * Requirements: + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for `sender`'s tokens of at least + * `amount`. + */ + function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) { + _transfer(sender, recipient, amount); + _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "BEP20: transfer amount exceeds allowance")); + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {BEP20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {BEP20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "BEP20: decreased allowance below zero")); + return true; + } + + /** + * @dev Moves tokens `amount` from `sender` to `recipient`. + * + * This is internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer(address sender, address recipient, uint256 amount) internal { + require(sender != address(0), "BEP20: transfer from the zero address"); + require(recipient != address(0), "BEP20: transfer to the zero address"); + + _balances[sender] = _balances[sender].sub(amount, "BEP20: transfer amount exceeds balance"); + _balances[recipient] = _balances[recipient].add(amount); + emit Transfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements + * + * - `to` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal { + require(account != address(0), "BEP20: mint to the zero address"); + + _totalSupply = _totalSupply.add(amount); + _balances[account] = _balances[account].add(amount); + emit Transfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal { + require(account != address(0), "BEP20: burn from the zero address"); + + _balances[account] = _balances[account].sub(amount, "BEP20: burn amount exceeds balance"); + _totalSupply = _totalSupply.sub(amount); + emit Transfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. + * + * This is 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. + */ + function _approve(address owner, address spender, uint256 amount) internal { + require(owner != address(0), "BEP20: approve from the zero address"); + require(spender != address(0), "BEP20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`.`amount` is then deducted + * from the caller's allowance. + * + * See {_burn} and {_approve}. + */ + function _burnFrom(address account, uint256 amount) internal { + _burn(account, amount); + _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "BEP20: burn amount exceeds allowance")); + } +} diff --git a/contracts/test/ERC20DEF.sol b/contracts/test/ERC20DEF.sol new file mode 100644 index 0000000..66e63be --- /dev/null +++ b/contracts/test/ERC20DEF.sol @@ -0,0 +1,598 @@ + +// File: contracts/interface/IBEP20.sol + +pragma solidity 0.6.4; + +interface IBEP20 { + /** + * @dev Returns the amount of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the token decimals. + */ + function decimals() external view returns (uint8); + + /** + * @dev Returns the token symbol. + */ + function symbol() external view returns (string memory); + + /** + * @dev Returns the token name. + */ + function name() external view returns (string memory); + + /** + * @dev Returns the bep token owner. + */ + function getOwner() external view returns (address); + + /** + * @dev Returns the amount of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Moves `amount` tokens from the caller's account to `recipient`. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transfer(address recipient, uint256 amount) external ; + + /** + * @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 `amount` 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 amount) external returns (bool); + + /** + * @dev Moves `amount` tokens from `sender` to `recipient` using the + * allowance mechanism. `amount` is then deducted from the caller's + * allowance. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transferFrom(address sender, address recipient, uint256 amount) external; + + /** + * @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); +} + +// File: openzeppelin-solidity/contracts/GSN/Context.sol + +pragma solidity ^0.6.0; + +/* + * @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 GSN 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. + */ +contract Context { + // Empty internal constructor, to prevent people from mistakenly deploying + // an instance of this contract, which should be used via inheritance. + constructor () internal { } + + function _msgSender() internal view virtual returns (address payable) { + return msg.sender; + } + + function _msgData() internal view virtual returns (bytes memory) { + this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 + return msg.data; + } +} + +// File: openzeppelin-solidity/contracts/math/SafeMath.sol + +pragma solidity ^0.6.0; + +/** + * @dev Wrappers over Solidity's arithmetic operations with added overflow + * checks. + * + * Arithmetic operations in Solidity wrap on overflow. This can easily result + * in bugs, because programmers usually assume that an overflow raises an + * error, which is the standard behavior in high level programming languages. + * `SafeMath` restores this intuition by reverting the transaction when an + * operation overflows. + * + * Using this library instead of the unchecked operations eliminates an entire + * class of bugs, so it's recommended to use it always. + */ +library SafeMath { + /** + * @dev Returns the addition of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `+` operator. + * + * Requirements: + * - Addition cannot overflow. + */ + function add(uint256 a, uint256 b) internal pure returns (uint256) { + uint256 c = a + b; + require(c >= a, "SafeMath: addition overflow"); + + return c; + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * - Subtraction cannot overflow. + */ + function sub(uint256 a, uint256 b) internal pure returns (uint256) { + return sub(a, b, "SafeMath: subtraction overflow"); + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting with custom message on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * - Subtraction cannot overflow. + */ + function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b <= a, errorMessage); + uint256 c = a - b; + + return c; + } + + /** + * @dev Returns the multiplication of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `*` operator. + * + * Requirements: + * - Multiplication cannot overflow. + */ + function mul(uint256 a, uint256 b) internal pure returns (uint256) { + // Gas optimization: this is cheaper than requiring 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 + if (a == 0) { + return 0; + } + + uint256 c = a * b; + require(c / a == b, "SafeMath: multiplication overflow"); + + return c; + } + + /** + * @dev Returns the integer division of two unsigned integers. Reverts on + * division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b) internal pure returns (uint256) { + return div(a, b, "SafeMath: division by zero"); + } + + /** + * @dev Returns the integer division of two unsigned integers. Reverts with custom message on + * division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + // Solidity only automatically asserts when dividing by 0 + require(b > 0, errorMessage); + uint256 c = a / b; + // assert(a == b * c + a % b); // There is no case in which this doesn't hold + + return c; + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * Reverts when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b) internal pure returns (uint256) { + return mod(a, b, "SafeMath: modulo by zero"); + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * Reverts with custom message when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b != 0, errorMessage); + return a % b; + } +} + +// File: openzeppelin-solidity/contracts/access/Ownable.sol + +pragma solidity ^0.6.0; + +/** + * @dev Contract module which provides a basic access control mechanism, where + * there is an account (an owner) that can be granted exclusive access to + * specific functions. + * + * By default, the owner account will be the one that deploys the contract. This + * can later be changed with {transferOwnership}. + * + * This module is used through inheritance. It will make available the modifier + * `onlyOwner`, which can be applied to your functions to restrict their use to + * the owner. + */ +contract Ownable is Context { + address private _owner; + + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + /** + * @dev Initializes the contract setting the deployer as the initial owner. + */ + constructor () internal { + address msgSender = _msgSender(); + _owner = msgSender; + emit OwnershipTransferred(address(0), msgSender); + } + + /** + * @dev Returns the address of the current owner. + */ + function owner() public view returns (address) { + return _owner; + } + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(_owner == _msgSender(), "Ownable: caller is not the owner"); + _; + } + + /** + * @dev Leaves the contract without owner. It will not be possible to call + * `onlyOwner` functions anymore. Can only be called by the current owner. + * + * NOTE: Renouncing ownership will leave the contract without an owner, + * thereby removing any functionality that is only available to the owner. + */ + function renounceOwnership() public virtual onlyOwner { + emit OwnershipTransferred(_owner, address(0)); + _owner = address(0); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + * Can only be called by the current owner. + */ + function transferOwnership(address newOwner) public virtual onlyOwner { + _transferOwnership(newOwner); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + */ + function _transferOwnership(address newOwner) internal virtual { + require(newOwner != address(0), "Ownable: new owner is the zero address"); + emit OwnershipTransferred(_owner, newOwner); + _owner = newOwner; + } +} + +// File: contracts/test/ABCToken.sol + +pragma solidity 0.6.4; + + + +contract ERC20DEF is Context, IBEP20, Ownable { + using SafeMath for uint256; + + mapping (address => uint256) private _balances; + + mapping (address => mapping (address => uint256)) private _allowances; + + uint256 private _totalSupply; + uint8 public _decimals; + string public _symbol; + string public _name; + + constructor() public { + _name = "ABC token"; + _symbol = "ABC"; + _decimals = 18; + _totalSupply = 100000000000000000000000000; + _balances[msg.sender] = _totalSupply; + + emit Transfer(address(0), msg.sender, _totalSupply); + } + + /** + * @dev Returns the bep token owner. + */ + function getOwner() external override view returns (address) { + return owner(); + } + + /** + * @dev Returns the token decimals. + */ + function decimals() external override view returns (uint8) { + return _decimals; + } + + /** + * @dev Returns the token symbol. + */ + function symbol() external override view returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the token name. + */ + function name() external override view returns (string memory) { + return _name; + } + + /** + * @dev See {BEP20-totalSupply}. + */ + function totalSupply() external override view returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {BEP20-balanceOf}. + */ + function balanceOf(address account) external override view returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {BEP20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) external override { + _transfer(_msgSender(), recipient, amount); + } + + /** + * @dev See {BEP20-allowance}. + */ + function allowance(address owner, address spender) external override view returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {BEP20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) external override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {BEP20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {BEP20}; + * + * Requirements: + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for `sender`'s tokens of at least + * `amount`. + */ + function transferFrom(address sender, address recipient, uint256 amount) external override { + _transfer(sender, recipient, amount); + _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "BEP20: transfer amount exceeds allowance")); + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {BEP20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {BEP20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "BEP20: decreased allowance below zero")); + return true; + } + + /** + * @dev Moves tokens `amount` from `sender` to `recipient`. + * + * This is internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer(address sender, address recipient, uint256 amount) internal { + require(sender != address(0), "BEP20: transfer from the zero address"); + require(recipient != address(0), "BEP20: transfer to the zero address"); + + _balances[sender] = _balances[sender].sub(amount, "BEP20: transfer amount exceeds balance"); + _balances[recipient] = _balances[recipient].add(amount); + emit Transfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements + * + * - `to` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal { + require(account != address(0), "BEP20: mint to the zero address"); + + _totalSupply = _totalSupply.add(amount); + _balances[account] = _balances[account].add(amount); + emit Transfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal { + require(account != address(0), "BEP20: burn from the zero address"); + + _balances[account] = _balances[account].sub(amount, "BEP20: burn amount exceeds balance"); + _totalSupply = _totalSupply.sub(amount); + emit Transfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. + * + * This is 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. + */ + function _approve(address owner, address spender, uint256 amount) internal { + require(owner != address(0), "BEP20: approve from the zero address"); + require(spender != address(0), "BEP20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`.`amount` is then deducted + * from the caller's allowance. + * + * See {_burn} and {_approve}. + */ + function _burnFrom(address account, uint256 amount) internal { + _burn(account, amount); + _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "BEP20: burn amount exceeds allowance")); + } +} diff --git a/contracts/test/ERC20EMPTYNAME.sol b/contracts/test/ERC20EMPTYNAME.sol new file mode 100644 index 0000000..09fd850 --- /dev/null +++ b/contracts/test/ERC20EMPTYNAME.sol @@ -0,0 +1,598 @@ + +// File: contracts/interface/IBEP20.sol + +pragma solidity 0.6.4; + +interface IBEP20 { + /** + * @dev Returns the amount of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the token decimals. + */ + function decimals() external view returns (uint8); + + /** + * @dev Returns the token symbol. + */ + function symbol() external view returns (string memory); + + /** + * @dev Returns the token name. + */ + function name() external view returns (string memory); + + /** + * @dev Returns the bep token owner. + */ + function getOwner() external view returns (address); + + /** + * @dev Returns the amount of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Moves `amount` tokens from the caller's account to `recipient`. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transfer(address recipient, uint256 amount) external ; + + /** + * @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 `amount` 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 amount) external returns (bool); + + /** + * @dev Moves `amount` tokens from `sender` to `recipient` using the + * allowance mechanism. `amount` is then deducted from the caller's + * allowance. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transferFrom(address sender, address recipient, uint256 amount) external; + + /** + * @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); +} + +// File: openzeppelin-solidity/contracts/GSN/Context.sol + +pragma solidity ^0.6.0; + +/* + * @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 GSN 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. + */ +contract Context { + // Empty internal constructor, to prevent people from mistakenly deploying + // an instance of this contract, which should be used via inheritance. + constructor () internal { } + + function _msgSender() internal view virtual returns (address payable) { + return msg.sender; + } + + function _msgData() internal view virtual returns (bytes memory) { + this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 + return msg.data; + } +} + +// File: openzeppelin-solidity/contracts/math/SafeMath.sol + +pragma solidity ^0.6.0; + +/** + * @dev Wrappers over Solidity's arithmetic operations with added overflow + * checks. + * + * Arithmetic operations in Solidity wrap on overflow. This can easily result + * in bugs, because programmers usually assume that an overflow raises an + * error, which is the standard behavior in high level programming languages. + * `SafeMath` restores this intuition by reverting the transaction when an + * operation overflows. + * + * Using this library instead of the unchecked operations eliminates an entire + * class of bugs, so it's recommended to use it always. + */ +library SafeMath { + /** + * @dev Returns the addition of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `+` operator. + * + * Requirements: + * - Addition cannot overflow. + */ + function add(uint256 a, uint256 b) internal pure returns (uint256) { + uint256 c = a + b; + require(c >= a, "SafeMath: addition overflow"); + + return c; + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * - Subtraction cannot overflow. + */ + function sub(uint256 a, uint256 b) internal pure returns (uint256) { + return sub(a, b, "SafeMath: subtraction overflow"); + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting with custom message on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * - Subtraction cannot overflow. + */ + function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b <= a, errorMessage); + uint256 c = a - b; + + return c; + } + + /** + * @dev Returns the multiplication of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `*` operator. + * + * Requirements: + * - Multiplication cannot overflow. + */ + function mul(uint256 a, uint256 b) internal pure returns (uint256) { + // Gas optimization: this is cheaper than requiring 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 + if (a == 0) { + return 0; + } + + uint256 c = a * b; + require(c / a == b, "SafeMath: multiplication overflow"); + + return c; + } + + /** + * @dev Returns the integer division of two unsigned integers. Reverts on + * division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b) internal pure returns (uint256) { + return div(a, b, "SafeMath: division by zero"); + } + + /** + * @dev Returns the integer division of two unsigned integers. Reverts with custom message on + * division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + // Solidity only automatically asserts when dividing by 0 + require(b > 0, errorMessage); + uint256 c = a / b; + // assert(a == b * c + a % b); // There is no case in which this doesn't hold + + return c; + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * Reverts when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b) internal pure returns (uint256) { + return mod(a, b, "SafeMath: modulo by zero"); + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * Reverts with custom message when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b != 0, errorMessage); + return a % b; + } +} + +// File: openzeppelin-solidity/contracts/access/Ownable.sol + +pragma solidity ^0.6.0; + +/** + * @dev Contract module which provides a basic access control mechanism, where + * there is an account (an owner) that can be granted exclusive access to + * specific functions. + * + * By default, the owner account will be the one that deploys the contract. This + * can later be changed with {transferOwnership}. + * + * This module is used through inheritance. It will make available the modifier + * `onlyOwner`, which can be applied to your functions to restrict their use to + * the owner. + */ +contract Ownable is Context { + address private _owner; + + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + /** + * @dev Initializes the contract setting the deployer as the initial owner. + */ + constructor () internal { + address msgSender = _msgSender(); + _owner = msgSender; + emit OwnershipTransferred(address(0), msgSender); + } + + /** + * @dev Returns the address of the current owner. + */ + function owner() public view returns (address) { + return _owner; + } + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(_owner == _msgSender(), "Ownable: caller is not the owner"); + _; + } + + /** + * @dev Leaves the contract without owner. It will not be possible to call + * `onlyOwner` functions anymore. Can only be called by the current owner. + * + * NOTE: Renouncing ownership will leave the contract without an owner, + * thereby removing any functionality that is only available to the owner. + */ + function renounceOwnership() public virtual onlyOwner { + emit OwnershipTransferred(_owner, address(0)); + _owner = address(0); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + * Can only be called by the current owner. + */ + function transferOwnership(address newOwner) public virtual onlyOwner { + _transferOwnership(newOwner); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + */ + function _transferOwnership(address newOwner) internal virtual { + require(newOwner != address(0), "Ownable: new owner is the zero address"); + emit OwnershipTransferred(_owner, newOwner); + _owner = newOwner; + } +} + +// File: contracts/test/ABCToken.sol + +pragma solidity 0.6.4; + + + +contract ERC20EMPTYNAME is Context, IBEP20, Ownable { + using SafeMath for uint256; + + mapping (address => uint256) private _balances; + + mapping (address => mapping (address => uint256)) private _allowances; + + uint256 private _totalSupply; + uint8 public _decimals; + string public _symbol; + string public _name; + + constructor() public { + _name = ""; + _symbol = ""; + _decimals = 18; + _totalSupply = 100000000000000000000000000; + _balances[msg.sender] = _totalSupply; + + emit Transfer(address(0), msg.sender, _totalSupply); + } + + /** + * @dev Returns the bep token owner. + */ + function getOwner() external override view returns (address) { + return owner(); + } + + /** + * @dev Returns the token decimals. + */ + function decimals() external override view returns (uint8) { + return _decimals; + } + + /** + * @dev Returns the token symbol. + */ + function symbol() external override view returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the token name. + */ + function name() external override view returns (string memory) { + return _name; + } + + /** + * @dev See {BEP20-totalSupply}. + */ + function totalSupply() external override view returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {BEP20-balanceOf}. + */ + function balanceOf(address account) external override view returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {BEP20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) external override { + _transfer(_msgSender(), recipient, amount); + } + + /** + * @dev See {BEP20-allowance}. + */ + function allowance(address owner, address spender) external override view returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {BEP20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) external override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {BEP20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {BEP20}; + * + * Requirements: + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for `sender`'s tokens of at least + * `amount`. + */ + function transferFrom(address sender, address recipient, uint256 amount) external override { + _transfer(sender, recipient, amount); + _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "BEP20: transfer amount exceeds allowance")); + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {BEP20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {BEP20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "BEP20: decreased allowance below zero")); + return true; + } + + /** + * @dev Moves tokens `amount` from `sender` to `recipient`. + * + * This is internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer(address sender, address recipient, uint256 amount) internal { + require(sender != address(0), "BEP20: transfer from the zero address"); + require(recipient != address(0), "BEP20: transfer to the zero address"); + + _balances[sender] = _balances[sender].sub(amount, "BEP20: transfer amount exceeds balance"); + _balances[recipient] = _balances[recipient].add(amount); + emit Transfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements + * + * - `to` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal { + require(account != address(0), "BEP20: mint to the zero address"); + + _totalSupply = _totalSupply.add(amount); + _balances[account] = _balances[account].add(amount); + emit Transfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal { + require(account != address(0), "BEP20: burn from the zero address"); + + _balances[account] = _balances[account].sub(amount, "BEP20: burn amount exceeds balance"); + _totalSupply = _totalSupply.sub(amount); + emit Transfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. + * + * This is 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. + */ + function _approve(address owner, address spender, uint256 amount) internal { + require(owner != address(0), "BEP20: approve from the zero address"); + require(spender != address(0), "BEP20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`.`amount` is then deducted + * from the caller's allowance. + * + * See {_burn} and {_approve}. + */ + function _burnFrom(address account, uint256 amount) internal { + _burn(account, amount); + _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "BEP20: burn amount exceeds allowance")); + } +} diff --git a/contracts/test/ERC20EMPTYSYMBOL.sol b/contracts/test/ERC20EMPTYSYMBOL.sol new file mode 100644 index 0000000..620228f --- /dev/null +++ b/contracts/test/ERC20EMPTYSYMBOL.sol @@ -0,0 +1,598 @@ + +// File: contracts/interface/IBEP20.sol + +pragma solidity 0.6.4; + +interface IBEP20 { + /** + * @dev Returns the amount of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the token decimals. + */ + function decimals() external view returns (uint8); + + /** + * @dev Returns the token symbol. + */ + function symbol() external view returns (string memory); + + /** + * @dev Returns the token name. + */ + function name() external view returns (string memory); + + /** + * @dev Returns the bep token owner. + */ + function getOwner() external view returns (address); + + /** + * @dev Returns the amount of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Moves `amount` tokens from the caller's account to `recipient`. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transfer(address recipient, uint256 amount) external ; + + /** + * @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 `amount` 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 amount) external returns (bool); + + /** + * @dev Moves `amount` tokens from `sender` to `recipient` using the + * allowance mechanism. `amount` is then deducted from the caller's + * allowance. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transferFrom(address sender, address recipient, uint256 amount) external; + + /** + * @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); +} + +// File: openzeppelin-solidity/contracts/GSN/Context.sol + +pragma solidity ^0.6.0; + +/* + * @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 GSN 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. + */ +contract Context { + // Empty internal constructor, to prevent people from mistakenly deploying + // an instance of this contract, which should be used via inheritance. + constructor () internal { } + + function _msgSender() internal view virtual returns (address payable) { + return msg.sender; + } + + function _msgData() internal view virtual returns (bytes memory) { + this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 + return msg.data; + } +} + +// File: openzeppelin-solidity/contracts/math/SafeMath.sol + +pragma solidity ^0.6.0; + +/** + * @dev Wrappers over Solidity's arithmetic operations with added overflow + * checks. + * + * Arithmetic operations in Solidity wrap on overflow. This can easily result + * in bugs, because programmers usually assume that an overflow raises an + * error, which is the standard behavior in high level programming languages. + * `SafeMath` restores this intuition by reverting the transaction when an + * operation overflows. + * + * Using this library instead of the unchecked operations eliminates an entire + * class of bugs, so it's recommended to use it always. + */ +library SafeMath { + /** + * @dev Returns the addition of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `+` operator. + * + * Requirements: + * - Addition cannot overflow. + */ + function add(uint256 a, uint256 b) internal pure returns (uint256) { + uint256 c = a + b; + require(c >= a, "SafeMath: addition overflow"); + + return c; + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * - Subtraction cannot overflow. + */ + function sub(uint256 a, uint256 b) internal pure returns (uint256) { + return sub(a, b, "SafeMath: subtraction overflow"); + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting with custom message on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * - Subtraction cannot overflow. + */ + function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b <= a, errorMessage); + uint256 c = a - b; + + return c; + } + + /** + * @dev Returns the multiplication of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `*` operator. + * + * Requirements: + * - Multiplication cannot overflow. + */ + function mul(uint256 a, uint256 b) internal pure returns (uint256) { + // Gas optimization: this is cheaper than requiring 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 + if (a == 0) { + return 0; + } + + uint256 c = a * b; + require(c / a == b, "SafeMath: multiplication overflow"); + + return c; + } + + /** + * @dev Returns the integer division of two unsigned integers. Reverts on + * division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b) internal pure returns (uint256) { + return div(a, b, "SafeMath: division by zero"); + } + + /** + * @dev Returns the integer division of two unsigned integers. Reverts with custom message on + * division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + // Solidity only automatically asserts when dividing by 0 + require(b > 0, errorMessage); + uint256 c = a / b; + // assert(a == b * c + a % b); // There is no case in which this doesn't hold + + return c; + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * Reverts when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b) internal pure returns (uint256) { + return mod(a, b, "SafeMath: modulo by zero"); + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * Reverts with custom message when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b != 0, errorMessage); + return a % b; + } +} + +// File: openzeppelin-solidity/contracts/access/Ownable.sol + +pragma solidity ^0.6.0; + +/** + * @dev Contract module which provides a basic access control mechanism, where + * there is an account (an owner) that can be granted exclusive access to + * specific functions. + * + * By default, the owner account will be the one that deploys the contract. This + * can later be changed with {transferOwnership}. + * + * This module is used through inheritance. It will make available the modifier + * `onlyOwner`, which can be applied to your functions to restrict their use to + * the owner. + */ +contract Ownable is Context { + address private _owner; + + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + /** + * @dev Initializes the contract setting the deployer as the initial owner. + */ + constructor () internal { + address msgSender = _msgSender(); + _owner = msgSender; + emit OwnershipTransferred(address(0), msgSender); + } + + /** + * @dev Returns the address of the current owner. + */ + function owner() public view returns (address) { + return _owner; + } + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(_owner == _msgSender(), "Ownable: caller is not the owner"); + _; + } + + /** + * @dev Leaves the contract without owner. It will not be possible to call + * `onlyOwner` functions anymore. Can only be called by the current owner. + * + * NOTE: Renouncing ownership will leave the contract without an owner, + * thereby removing any functionality that is only available to the owner. + */ + function renounceOwnership() public virtual onlyOwner { + emit OwnershipTransferred(_owner, address(0)); + _owner = address(0); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + * Can only be called by the current owner. + */ + function transferOwnership(address newOwner) public virtual onlyOwner { + _transferOwnership(newOwner); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + */ + function _transferOwnership(address newOwner) internal virtual { + require(newOwner != address(0), "Ownable: new owner is the zero address"); + emit OwnershipTransferred(_owner, newOwner); + _owner = newOwner; + } +} + +// File: contracts/test/ABCToken.sol + +pragma solidity 0.6.4; + + + +contract ERC20EMPTYSYMBOL is Context, IBEP20, Ownable { + using SafeMath for uint256; + + mapping (address => uint256) private _balances; + + mapping (address => mapping (address => uint256)) private _allowances; + + uint256 private _totalSupply; + uint8 public _decimals; + string public _symbol; + string public _name; + + constructor() public { + _name = "ACD"; + _symbol = ""; + _decimals = 18; + _totalSupply = 100000000000000000000000000; + _balances[msg.sender] = _totalSupply; + + emit Transfer(address(0), msg.sender, _totalSupply); + } + + /** + * @dev Returns the bep token owner. + */ + function getOwner() external override view returns (address) { + return owner(); + } + + /** + * @dev Returns the token decimals. + */ + function decimals() external override view returns (uint8) { + return _decimals; + } + + /** + * @dev Returns the token symbol. + */ + function symbol() external override view returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the token name. + */ + function name() external override view returns (string memory) { + return _name; + } + + /** + * @dev See {BEP20-totalSupply}. + */ + function totalSupply() external override view returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {BEP20-balanceOf}. + */ + function balanceOf(address account) external override view returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {BEP20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) external override { + _transfer(_msgSender(), recipient, amount); + } + + /** + * @dev See {BEP20-allowance}. + */ + function allowance(address owner, address spender) external override view returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {BEP20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) external override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {BEP20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {BEP20}; + * + * Requirements: + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for `sender`'s tokens of at least + * `amount`. + */ + function transferFrom(address sender, address recipient, uint256 amount) external override { + _transfer(sender, recipient, amount); + _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "BEP20: transfer amount exceeds allowance")); + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {BEP20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {BEP20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "BEP20: decreased allowance below zero")); + return true; + } + + /** + * @dev Moves tokens `amount` from `sender` to `recipient`. + * + * This is internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer(address sender, address recipient, uint256 amount) internal { + require(sender != address(0), "BEP20: transfer from the zero address"); + require(recipient != address(0), "BEP20: transfer to the zero address"); + + _balances[sender] = _balances[sender].sub(amount, "BEP20: transfer amount exceeds balance"); + _balances[recipient] = _balances[recipient].add(amount); + emit Transfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements + * + * - `to` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal { + require(account != address(0), "BEP20: mint to the zero address"); + + _totalSupply = _totalSupply.add(amount); + _balances[account] = _balances[account].add(amount); + emit Transfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal { + require(account != address(0), "BEP20: burn from the zero address"); + + _balances[account] = _balances[account].sub(amount, "BEP20: burn amount exceeds balance"); + _totalSupply = _totalSupply.sub(amount); + emit Transfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. + * + * This is 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. + */ + function _approve(address owner, address spender, uint256 amount) internal { + require(owner != address(0), "BEP20: approve from the zero address"); + require(spender != address(0), "BEP20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`.`amount` is then deducted + * from the caller's allowance. + * + * See {_burn} and {_approve}. + */ + function _burnFrom(address account, uint256 amount) internal { + _burn(account, amount); + _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "BEP20: burn amount exceeds allowance")); + } +} diff --git a/generate-bsc-swap-agent.js b/generate-bsc-swap-agent.js new file mode 100644 index 0000000..948e7f8 --- /dev/null +++ b/generate-bsc-swap-agent.js @@ -0,0 +1,39 @@ +const program = require("commander"); +const fs = require("fs"); +const nunjucks = require("nunjucks"); + +program.version("0.0.1"); +program.option( + "-t, --template