• Base Contracts
Here is a full sample contract with all needed functions to use in the DETA Swap 2.0
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./interfaces/IERC20.sol";
import "./interfaces/IDETASwapFactory.sol";
import "./interfaces/IDETASwapRouter.sol";
contract DETASwap_Base is IERC20, Ownable {
using SafeMath for uint256;
using Address for address;
// Fees
// Add and remove fee types and destinations here as needed
struct Fees {
uint256 marketingFee;
uint256 developmentFee;
address marketingAddress;
address developmentAddress;
}
// Transaction fee values
// Add and remove fee value types here as needed
struct FeeValues {
uint256 transferAmount;
uint256 marketing;
uint256 development;
}
// Token details
mapping (address => uint256) _balances;
mapping (address => mapping (address => uint256)) private _allowances;
// Set total supply here
uint256 private _tTotal = 10 * 10**9 * 10**9;
// Users states
mapping (address => bool) private _isExcludedFromFee;
mapping (address => bool) isTxLimitExempt;
// Pair Details
mapping (uint256 => address) private pairs;
mapping (uint256 => address) private tokens;
uint256 private pairsLength;
mapping (address => bool) public _isPairAddress;
// Outside Swap Pairs
mapping (address => bool) private _includeSwapFee;
// Set the name, symbol, and decimals here
string constant _name = "DETASwap_Base";
string constant _symbol = "BASE";
uint8 constant _decimals = 9;
Fees private _defaultFees;
Fees public _buyFees;
Fees private _previousFees;
Fees private _emptyFees;
Fees public _sellFees;
Fees private _outsideBuyFees;
Fees private _outsideSellFees;
IDETASwapRouter public DETASwapRouter;
address public DETASwapPair;
address public WBNB;
address public _burnAddress = 0x000000000000000000000000000000000000dEaD;
uint256 public _maxTxAmount = 5 * 10**8 * 10**9;
bool public swapEnabled = true;
uint256 public swapThreshold = 5 * 10**14; // 0.0005 WBNB
bool inSwap;
modifier swapping() { inSwap = true; _; inSwap = false; }
modifier onlyExchange() {
bool isPair = false;
for(uint i = 0; i < pairsLength; i++) {
if(pairs[i] == msg.sender) isPair = true;
}
require(
msg.sender == address(DETASwapRouter)
|| isPair
, "DETA: NOT_ALLOWED"
);
_;
}
// Edit the constructor in order to declare default fees on deployment
constructor(address _router, address _marketing, uint256 _marketingFeeBuy, uint256 _marketingFeeSell, address _development, uint256 _developmentFeeBuy, uint256 _developmentFeeSell) {
_balances[_msgSender()] = _tTotal;
DETASwapRouter = IDETASwapRouter(_router);
WBNB = DETASwapRouter.WETH();
DETASwapPair = IDETASwapFactory(DETASwapRouter.factory())
.createPair(address(this), WBNB, true, address(this));
tokens[pairsLength] = WBNB;
pairs[pairsLength] = DETASwapPair;
pairsLength += 1;
_isPairAddress[DETASwapPair] = true;
_isExcludedFromFee[_msgSender()] = true;
_isExcludedFromFee[DETASwapPair] = true;
isTxLimitExempt[_msgSender()] = true;
isTxLimitExempt[DETASwapPair] = true;
isTxLimitExempt[address(DETASwapRouter)] = true;
// This should match the struct Fee
_defaultFees = Fees(
_marketingFeeBuy,
_developmentFeeBuy,
_marketing,
_development
);
_buyFees = Fees(
_marketingFeeBuy,
_developmentFeeBuy,
_marketing,
_development
);
_sellFees = Fees(
_marketingFeeSell,
_developmentFeeSell,
_marketing,
_development
);
_outsideBuyFees = Fees(
_marketingFeeBuy,
_developmentFeeBuy,
_marketing,
_development
);
_outsideSellFees = Fees(
_marketingFeeSell,
_developmentFeeSell,
_marketing,
_development
);
emit Transfer(address(0), _msgSender(), _tTotal);
}
function name() public pure returns (string memory) {
return _name;
}
function symbol() public pure returns (string memory) {
return _symbol;
}
function decimals() public pure returns (uint8) {
return _decimals;
}
function totalSupply() public view override returns (uint256) {
return _tTotal;
}
function balanceOf(address account) public view override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "BEP20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "BEP20: decreased allowance below zero"));
return true;
}
function excludeFromFee(address account) public onlyOwner {
_isExcludedFromFee[account] = true;
}
function includeInFee(address account) public onlyOwner {
_isExcludedFromFee[account] = false;
}
// Functions to update fees and addresses
// set fee values on buys
function setBuyFees(uint256 _marketingFee, uint256 _developmentFee) external onlyOwner {
_defaultFees.marketingFee = _marketingFee;
_defaultFees.developmentFee = _developmentFee;
_buyFees.marketingFee = _marketingFee;
_buyFees.developmentFee = _developmentFee;
_outsideBuyFees.marketingFee = _marketingFee;
_outsideBuyFees.developmentFee = _developmentFee;
}
// set fee values on sells
function setSellFees(uint256 _marketingFee, uint256 _developmentFee) external onlyOwner {
_sellFees.marketingFee = _marketingFee;
_sellFees.developmentFee = _developmentFee;
_outsideSellFees.marketingFee = _marketingFee;
_outsideSellFees.developmentFee = _developmentFee;
}
function setDevelopmentAddress(address _development) external onlyOwner {
require(_development != address(0), "DETA: Address Zero is not allowed");
_defaultFees.developmentAddress = _development;
_buyFees.developmentAddress = _development;
_sellFees.developmentAddress = _development;
_outsideBuyFees.developmentAddress = _development;
_outsideSellFees.developmentAddress = _development;
}
function setMarketingAddress(address _marketing) external onlyOwner {
require(_marketing != address(0), "DETA: Address Zero is not allowed");
_defaultFees.marketingAddress = _marketing;
_buyFees.marketingAddress = _marketing;
_sellFees.marketingAddress = _marketing;
_outsideBuyFees.marketingAddress = _marketing;
_outsideSellFees.marketingAddress = _marketing;
}
function updateRouterAndPair(address _router, address _pair) public onlyOwner {
_isExcludedFromFee[DETASwapPair] = false;
DETASwapRouter = IDETASwapRouter(_router);
DETASwapPair = _pair;
WBNB = DETASwapRouter.WETH();
_isExcludedFromFee[DETASwapPair] = true;
_isPairAddress[DETASwapPair] = true;
isTxLimitExempt[DETASwapPair] = true;
isTxLimitExempt[address(DETASwapRouter)] = true;
pairs[0] = DETASwapPair;
tokens[0] = WBNB;
}
function addOutsideSwapPair(address account) public onlyOwner {
_includeSwapFee[account] = true;
}
function removeOutsideSwapPair(address account) public onlyOwner {
_includeSwapFee[account] = false;
}
// To update the max tx amount
function setMaxTxPercent(uint256 maxTxPercent) external onlyOwner {
_maxTxAmount = _tTotal.mul(maxTxPercent).div(
10**4
);
}
//to receive BNB from DETARouter when swapping
receive() external payable {}
function _getValues(uint256 tAmount) private view returns (FeeValues memory) {
FeeValues memory values = FeeValues(
0,
calculateFee(tAmount, _defaultFees.marketingFee),
calculateFee(tAmount, _defaultFees.developmentFee)
);
values.transferAmount = tAmount.sub(values.marketing).sub(values.development);
return values;
}
function calculateFee(uint256 _amount, uint256 _fee) private pure returns (uint256) {
if(_fee == 0) return 0;
return _amount.mul(_fee).div(
10**4
);
}
function removeAllFee() private {
_previousFees = _defaultFees;
_defaultFees = _emptyFees;
}
function setSellFee() private {
_defaultFees = _sellFees;
}
function setOutsideBuyFee() private {
_previousFees = _defaultFees;
_defaultFees = _outsideBuyFees;
}
function setOutsideSellFee() private {
_previousFees = _defaultFees;
_defaultFees = _outsideSellFees;
}
function restoreAllFee() private {
_defaultFees = _previousFees;
}
function isExcludedFromFee(address account) public view returns(bool) {
return _isExcludedFromFee[account];
}
function _approve(
address owner,
address spender,
uint256 amount
) private {
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);
}
function getBalance(address keeper) public view returns (uint256){
return _balances[keeper];
}
function _transfer(
address from,
address to,
uint256 amount
) private {
require(from != address(0), "BEP20: transfer from the zero address");
require(to != address(0), "BEP20: transfer to the zero address");
require(amount > 0, "Transfer amount must be greater than zero");
checkTxLimit(from, amount);
//indicates if fee should be deducted from transfer of tokens
uint8 takeFee = 0;
if(_isPairAddress[to] && from != address(DETASwapRouter) && !isExcludedFromFee(from)) {
takeFee = 1;
} else if(_includeSwapFee[from]) {
takeFee = 2;
} else if(_includeSwapFee[to]) {
takeFee = 3;
}
//transfer amount, it will take tax
_tokenTransfer(from, to, amount, takeFee);
}
function getCirculatingSupply() public view returns (uint256) {
return _tTotal.sub(balanceOf(_burnAddress)).sub(balanceOf(address(0)));
}
function getTotalFee(address account) public view returns (uint256) {
if(_isExcludedFromFee[account]) {
return 0;
} else {
return _defaultFees.marketingFee
.add(_defaultFees.developmentFee);
}
}
function getFee() public view returns (uint256) {
return _defaultFees.marketingFee
.add(_defaultFees.developmentFee);
}
//this method is responsible for taking all fee, if takeFee is true
function _tokenTransfer(address sender, address recipient, uint256 amount, uint8 takeFee) private {
if(takeFee == 0 || takeFee == 1) {
removeAllFee();
} else if(takeFee == 2) {
setOutsideBuyFee();
} else if(takeFee == 3) {
setOutsideSellFee();
}
FeeValues memory _values = _getValues(amount);
_balances[sender] = _balances[sender].sub(amount, "Insufficient Balance");
_balances[recipient] = _balances[recipient].add(_values.transferAmount);
_takeFees(_values);
emit Transfer(sender, recipient, _values.transferAmount);
if(takeFee == 0) {
restoreAllFee();
} else if(takeFee == 1) {
setSellFee();
} else if(takeFee == 2 || takeFee == 3) {
restoreAllFee();
emit Transfer(sender, _defaultFees.developmentAddress, _values.development);
emit Transfer(sender, _defaultFees.marketingAddress, _values.marketing);
}
}
function _takeFees(FeeValues memory values) private {
_takeFee(values.marketing, _defaultFees.marketingAddress);
_takeFee(values.development, _defaultFees.developmentAddress);
}
function _takeFee(uint256 tAmount, address recipient) private {
if(recipient == address(0)) return;
if(tAmount == 0) return;
_balances[address(this)] = _balances[address(this)].add(tAmount);
}
function setIsTxLimitExempt(address holder, bool exempt) external onlyOwner {
isTxLimitExempt[holder] = exempt;
}
function checkTxLimit(address sender, uint256 amount) internal view {
require(amount <= _maxTxAmount || isTxLimitExempt[sender], "TX Limit Exceeded");
}
// This function transfers the fees to the correct addresses.
function handleFee(uint256 amount, address token) public onlyExchange {
uint256 tokenIndex = _getTokenIndex(token);
if(tokenIndex < pairsLength) {
uint256 allowanceT = IERC20(token).allowance(msg.sender, address(this));
if(allowanceT >= amount) {
IERC20(token).transferFrom(msg.sender, address(this), amount);
// All fees to be declared here in order to be calculated and sent
uint256 totalFee = getFee();
uint256 marketingFeeAmount = amount.mul(_defaultFees.marketingFee).div(totalFee);
uint256 developmentFeeAmount = amount.mul(_defaultFees.developmentFee).div(totalFee);
IERC20(token).transfer(_defaultFees.marketingAddress, marketingFeeAmount);
IERC20(token).transfer(_defaultFees.developmentAddress, developmentFeeAmount);
restoreAllFee();
}
}
}
function _getTokenIndex(address _token) internal view returns (uint256) {
uint256 index = pairsLength + 1;
for(uint256 i = 0; i < pairsLength; i++) {
if(tokens[i] == _token) index = i;
}
return index;
}
function addPair(address _pair, address _token) public {
address factory = DETASwapRouter.factory();
require(
msg.sender == factory
|| msg.sender == address(DETASwapRouter)
|| msg.sender == address(this)
, "DETA: NOT_ALLOWED"
);
if(!_checkPairRegistered(_pair)) {
_isExcludedFromFee[_pair] = true;
_isPairAddress[_pair] = true;
isTxLimitExempt[_pair] = true;
pairs[pairsLength] = _pair;
tokens[pairsLength] = _token;
pairsLength += 1;
}
}
function _checkPairRegistered(address _pair) internal view returns (bool) {
bool isPair = false;
for(uint i = 0; i < pairsLength; i++) {
if(pairs[i] == _pair) isPair = true;
}
return isPair;
}
// Rescue bnb that is sent here by mistake
function rescueBNB(uint256 amount, address to) external onlyOwner{
payable(to).transfer(amount);
}
// Rescue tokens that are sent here by mistake
function rescueToken(IERC20 token, uint256 amount, address to) external onlyOwner {
if( token.balanceOf(address(this)) < amount ) {
amount = token.balanceOf(address(this));
}
token.transfer(to, amount);
}
}
```
Last updated