Skip to content

Instantly share code, notes, and snippets.

@parnaa
Created March 26, 2021 03:43
Show Gist options
  • Save parnaa/7e359e1795f5460d0d53a15919bf15e9 to your computer and use it in GitHub Desktop.
Save parnaa/7e359e1795f5460d0d53a15919bf15e9 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.7.6+commit.7338295f.js&optimize=false&runs=200&gist=
Swap Factory Contract
===================================
Any BEP20 token can be swapped with FXP (Fixed Swap Pool Token) by creating unique swap pool for each BEP20 Token in Binance Smart Chain
Each swap process burn the swapped Token
Pool Creation:==>
====================================
call buildTokenPool function with parameters as the token contract address which for the pool is being created
and initial FXP limit of the pool (which will decide the swap rate of the pool)
Once the pool is created, The proposed amount of FXP need to be deposited to the pool
Need to call the checkerAndActivator function of the pool , which will check if the FXP limit reached, if reached it will activate the pool.
Once Pool is activated , now anybody having the particular token , which for the pool is made can send a swap request and according to swaprate(swaprate can be checked once pool is activated)
they can receive FXP
NOTE: FXP can never be withdrawn other than sending a swap request
Swapping Mechanism:==>
=================================
--> The amount of tokens to be swapped must be approved by the requestor and allow the factory contract address as spender
--> Then call "swapToken" function of Factory contract with parameters like the BEP20 token address of the TokenPool and amount of tokens
to be swapped. Then rest the function itself will take care of
How the swap request (call to the swapToken function) is handled -->
--> The factory will deduct the approved amount of tokens from requestor's address and will transfer it to the TokenPool, then rest of swapping process
will be taken care of by the TokenPool's swap function , which will send the tokens to burner and calculate the amount of FXP the requestor should get
according to the swaprate and will transfer that FXP to the requestor
*** IMPORTANT NOTE ***
Swap request can be made only by calling the swapToken function from factory contract
Burning Mechanism :==>
==============================
A burner contract created for each swap request , swappable tokens are transferred to the burner for each request,
after that selfDestruct call is made, which destroys the burner contract of the swapped tokens, hence make the swapped tokens completely inaccssible
Some security implementation :=>
===========================================
Reentrancyguard applied (using openzepplin library) for swap request , hence guarding the state changes;
As no smart contract can stop receiving BEP20 tokens which are not intended ,
so if any such case happens where someone accidentally deposit wrong tokens to either factory contract address or Pool contract adddess created by the factory
contract, then the factory contract owner (who has deployed the contract / who has been given the ownership of the factory contract) can have access to call two functions
of factory contract,
withdrawTokenFromcontract -- This function can transfer any tokens deposited to factory contract from its own address to the caller i.e. the factory contract owner
withdrawTokenFromPoolContract -- This function will call the withdraw function of the corresponding pool contract (pool address sent as parameter) and the corresponding tokens
if present in the pool, will be transferred back to the factory contract. But this function is not allowed to withdraw FXP ,
which is set as the base currency to return for swapped tokens. Once withdrawn tokens sent back to factory . Now the factory
owner can again call withdrawTokenFromcontract function and withdraw to his own wallet address.
Its owner's responsibility how will he deal with these accidentally deposited tokens after withdrawal .
While pool's withdrawal function called, a modifier "swapNotOnProgress" is applied to check whether any swap request is in progress or not,
if any swap request is in progress the withdrawal request will be reverted to avoid any redundancy regarding state changes of the swaprequest function
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.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 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) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
/**
* @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.
*/
abstract 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 () {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual 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;
}
}
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain`call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
abstract contract BEP20Token {
//totalsupply
function totalSupply() public view virtual returns (uint256 _totalSupply);
/// @param _owner The address from which the balance will be retrieved
function balanceOf(address _owner) public view virtual returns (uint256 balance);
/// @notice send `_value` token to `_to` from `msg.sender`
/// @param _to The address of the recipient
/// @param _value The amount of token to be transferred
function transfer(address _to, uint256 _value) public virtual returns (bool success);
/// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
/// @param _from The address of the sender
/// @param _to The address of the recipient
/// @param _value The amount of token to be transferred
function transferFrom(address _from, address _to, uint256 _value) public virtual returns (bool success);
function approve(address _spender, uint256 _value) public virtual returns (bool success);
function disApprove(address _spender) public virtual returns (bool success);
/// @param owner The address of the account owning tokens
/// @param spender The address of the account able to transfer the tokens
function allowance(address owner, address spender) public view virtual returns (uint256 _allowances);
function increaseAllowance(address _spender, uint _addedValue) public virtual returns (bool success);
function decreaseAllowance(address _spender, uint _subtractedValue) public virtual returns (bool success);
function name() public view virtual returns (string memory);
/* Get the contract constant _symbol */
function symbol() public view virtual returns (string memory);
/* Get the contract constant _decimals */
function decimals() public view virtual returns (uint8 _decimals);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
}
/**
* @title SafeBEP20
* @dev Wrappers around BEP20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeBEP20 for IBEP20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeBEP20 {
using Address for address;
function safeTransfer(BEP20Token token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(BEP20Token token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IBEP20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(BEP20Token token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// solhint-disable-next-line max-line-length
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeBEP20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(BEP20Token token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(BEP20Token token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeBEP20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(BEP20Token token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeBEP20: low-level call failed");
if (returndata.length > 0) { // Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeBEP20: BEP20 operation did not succeed");
}
}
}
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*/
abstract contract ReentrancyGuarded {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor () {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}
/**
* TokenBurner Contract is a selfDestructive contract where the swapped tokens are sent for burning and the contract destroy itself
*
*
**/
contract TokenBurner is ReentrancyGuarded{
BEP20Token private token;
uint256 private amountToBeBurned;
constructor(
BEP20Token _tokenaddress,
uint256 _amount
)
{
token = _tokenaddress;
amountToBeBurned = _amount;
}
function letBurn() public nonReentrant
{
_destroy();
}
function _destroy() internal {
selfdestruct(payable(address(this)));
}
}
/*
Unique Token Pool contract with ETH vault for swap
*/
contract FXPTokenSwapPoolContract is ReentrancyGuarded, Ownable {
using SafeBEP20 for BEP20Token; //SafeBEP20 library used for safe transfer of tokens
event Received(address,uint256); // Ether received event triggered when ether is added to this vault
event SwapRateChangedTo(uint256);
event Swapped(address,uint256); // Swapped event triggered once tokens are swapped
BEP20Token public tokenContractAddress; // The unique token contract address of the token pool
uint256 public proposedFXPInVault; // the ether limit of the vault in wei which is changed when swapped or more ethers are added
string public poolName; //The name of the token is set as the name of the Pool
uint256 public poolTokenSupply; // Token Supply of this token Pool
bool poolActiveStatus; // 'true' value means active status and 'false' value means not active
bool swapRequestStatus; // 'true' value means a swap request is in progress
BEP20Token public poolBaseCurrencyFXP;
constructor(
BEP20Token _tokenaddress, // takes the token address as parameter
uint256 _FXP_su_in_vault, // inittialize with ether limit at beiginning in FXP . su stands for smallest unit
BEP20Token _baseCurrencyFXP
)
{
tokenContractAddress = _tokenaddress; // initialize with token address
proposedFXPInVault = _FXP_su_in_vault ; // inittialize with ether limit ata beiginning which needed to deposited
poolName = tokenContractAddress.name(); //pool name
poolTokenSupply = tokenContractAddress.totalSupply(); // initialize with the token's totalsupply
poolActiveStatus = false; // initialize with inactive status i.e. 'false'
swapRequestStatus = false;
poolBaseCurrencyFXP = _baseCurrencyFXP;
}
//modifier to check whether pool is active or not
modifier poolActive(){
require(poolActiveStatus, "This pool is currently not activated");
_;
}
//modifier to check whether pool is active or not
modifier swapNotOnProgress(){
require(!swapRequestStatus, "A swap request is in progress");
_;
}
function checkerAndActivator() public
{
require(poolBaseCurrencyFXP.balanceOf(address(this)) >= proposedFXPInVault);
proposedFXPInVault = poolBaseCurrencyFXP.balanceOf(address(this));
if(!poolActiveStatus)
poolActiveStatus = true;
emit SwapRateChangedTo(swapRate());
}
/*
returns swap rate of 1 token in wei
*/
function swapRate() public view poolActive returns(uint256 _ramount)
{
require(poolTokenSupply != 0, "Token supply is 0");
return uint256((proposedFXPInVault * (10 ** uint256(tokenContractAddress.decimals()))) / poolTokenSupply); // swap rate of 1 Token in smallest FXP unit
}
/*_requestor parameter takes the address of the user who sent swap request
* _amount parameter takes the exact amount of tokens to be swapped (not the smallest unit)
*/
function requestSwap(address _requestor, uint256 _amount) public nonReentrant poolActive onlyOwner
{
require(poolBaseCurrencyFXP.balanceOf(address(this)) >= proposedFXPInVault,"Full proposed amount of FXP not deposited yet");
require(_requestor != address(0));
require(tokenContractAddress.balanceOf(address(this)) >= (_amount * (10 ** uint256(tokenContractAddress.decimals()))));
swapRequestStatus = true;
// calculate sufxp ( FXP smallest Unit) amount according to currenct swap rate
uint256 swapedsufxpamount = _amount * swapRate();
//smallesttoken units
uint256 smallestTokenUnits = _amount * (10 ** uint256(tokenContractAddress.decimals()));
//update pools FXP balance limit
proposedFXPInVault = poolBaseCurrencyFXP.balanceOf(address(this)) - swapedsufxpamount;
//burn the amount of tokens from requestors tokenbalance, deduct the supply first before transferring the tokens to burner to avoid redundancy
poolTokenSupply -= smallestTokenUnits;
//create tokenburner contract for current swapable amount of tokens
TokenBurner lit = new TokenBurner(tokenContractAddress, smallestTokenUnits); //create burner contract for the swapped amount of tokens
SafeBEP20.safeTransfer(tokenContractAddress,address(lit), smallestTokenUnits); // transfer the swapped tokens to the burner
lit.letBurn(); // Burn
//send FXP as per the swap rate
SafeBEP20.safeTransfer(poolBaseCurrencyFXP, _requestor,swapedsufxpamount);
swapRequestStatus = false;
emit Swapped(_requestor, _amount);
}
//function for withdrawal of accidentally deposited tokens to this pool, only the factory contract can call
function _withdrawTokenFromContract(BEP20Token _token, uint256 _tamount) public nonReentrant swapNotOnProgress onlyOwner{
require(_token != poolBaseCurrencyFXP, "FXP withdrawal from Pools not allowed");
SafeBEP20.safeTransfer(_token,msg.sender, _tamount);
}
}
/*
The factory contract to create Token Pools for swapping with ETH
*/
contract FXPTokenPairFactory is Ownable, ReentrancyGuarded{
using SafeBEP20 for BEP20Token;
//pooldetails storing the details of a created tokenpool
struct PoolDetails{
string poolName;
address poolCreator;
FXPTokenSwapPoolContract tokenPool;
uint256 totalGrantedEthAmount;
BEP20Token tokenAddress;
bool exist;
}
mapping (address => PoolDetails) public PoolsRecords; //map of addresses referencing to pooldetails record
address[] public tokenPools; // array of addresses which are essentially the keys of the mapping above
uint32 public numOfPools = 0 ; //initialize numOfPools with 0
BEP20Token public FXPToken = BEP20Token(0xcbCb6F86238afdb98516fb5D70601B17A386598c); //FXPToken is what, user will get after swapping
event TokenPoolCreated(FXPTokenSwapPoolContract);
//create the token pool contract
function createTokenPoolContract(BEP20Token _tokenaddr, uint256 FXPInPool) private returns(FXPTokenSwapPoolContract)
{
require(_tokenaddr != FXPToken);
uint256 smallestUnitFXPInpool = FXPInPool * (10 ** FXPToken.decimals());
FXPTokenSwapPoolContract swapContract = new FXPTokenSwapPoolContract(_tokenaddr,smallestUnitFXPInpool,FXPToken);
return swapContract;
}
//call pool contract create function and put record
function buildTokenPool(BEP20Token _tokenaddr, uint256 FXPInPool) public nonReentrant
{
require(!PoolsRecords[address(_tokenaddr)].exist, "The token pool already exists");
FXPTokenSwapPoolContract swapContractAddress = createTokenPoolContract(_tokenaddr,FXPInPool);
PoolsRecords[address(_tokenaddr)] = PoolDetails({
poolName: _tokenaddr.name(),
poolCreator: msg.sender,
tokenPool: swapContractAddress,
totalGrantedEthAmount: FXPInPool,
tokenAddress: _tokenaddr,
exist: true
});
numOfPools += 1;
tokenPools.push(address(_tokenaddr));
emit TokenPoolCreated(swapContractAddress);
}
//check if token pool exist
function tokenPoolExist(BEP20Token _tokenaddr) public view returns(bool)
{
return(PoolsRecords[address(_tokenaddr)].exist);
}
//get the token pool address if the token pool already exist
function getTokenPoolAddress(BEP20Token _tokenaddr) external view returns(FXPTokenSwapPoolContract _tokenPool)
{
require(PoolsRecords[address(_tokenaddr)].exist, "The token pool does not exist");
return PoolsRecords[address(_tokenaddr)].tokenPool;
}
//checker and activator --- call function from pool
function poolCheckerAndActivator(BEP20Token _tokenaddr) public
{
require(PoolsRecords[address(_tokenaddr)].exist, "The token pool does not exist");
PoolsRecords[address(_tokenaddr)].tokenPool.checkerAndActivator();
}
//get the token pool swap rate
function getTokenSwapRate(BEP20Token _tokenaddr) external view returns(uint256 _swaprate)
{
require(PoolsRecords[address(_tokenaddr)].exist, "The token pool does not exist");
return PoolsRecords[address(_tokenaddr)].tokenPool.swapRate();
}
//get the amount of FXP limit in the pool
function getTokenPoolFXPLimit(BEP20Token _tokenaddr) external view returns(uint256 _balanceINwei)
{
require(PoolsRecords[address(_tokenaddr)].exist, "The token pool does not exist");
return PoolsRecords[address(_tokenaddr)].tokenPool.proposedFXPInVault();
}
//get the amount of token supply in pool
function getTokenPoolSupply(BEP20Token _tokenaddr) external view returns(uint256 _balanceINwei)
{
require(PoolsRecords[address(_tokenaddr)].exist, "The token pool does not exist");
return PoolsRecords[address(_tokenaddr)].tokenPool.poolTokenSupply();
}
/**** IMPORTANT : Before calling this function the user needs to appove the swapable amount to be spent by the factory address, ****
***if factory contract address is not added as allowance of the token contract swap will not take place and function will revert ***/
//swap token
function swapToken(BEP20Token _tokenaddr, uint256 _amount) public nonReentrant
{
require(PoolsRecords[address(_tokenaddr)].exist, "The token pool does not exist");
require(_tokenaddr.allowance(msg.sender,address(this)) >= _amount);
uint256 smallestTokenUnits = _amount * (10 ** uint256(_tokenaddr.decimals()));
//transfer the tokens to the pool which will be burnt after swapping
SafeBEP20.safeTransferFrom(_tokenaddr, msg.sender, address(PoolsRecords[address(_tokenaddr)].tokenPool),smallestTokenUnits);
//swap request to token pool
PoolsRecords[address(_tokenaddr)].tokenPool.requestSwap(msg.sender, _amount);
}
//function for withdrawal of accidentally deposited tokens to factory, only the factory contract owner can call
function withdrawTokenFromcontract(BEP20Token _token, uint256 _tamount) public onlyOwner{
require(_token.balanceOf(address(this)) >= _tamount);
SafeBEP20.safeTransfer(_token,msg.sender, _tamount);
}
//function for withdrawal of accidentally deposited tokens ( other than FXP ) to any pool
function withdrawTokenFromPoolContract(BEP20Token _token, FXPTokenSwapPoolContract _pool, uint256 _tamount) public onlyOwner{
require(_token != FXPToken, "You can not withdraw FXP from any POOL");
//uint256 blnc = FXPToken.balanceOf(address(this));
_pool._withdrawTokenFromContract(_token,_tamount);
}
}
pragma solidity ^0.7.0;
// SPDX-License-Identifier: MIT
/**
* @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);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
assert(c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a / b;
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
function ceil(uint256 a, uint256 m) internal pure returns (uint256) {
uint256 c = add(a,m);
uint256 d = sub(c,1);
return mul(div(d,m),m);
}
}
contract FixedSwapProtocol is IERC20 {
using SafeMath for uint256;
mapping (address => uint256) public _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
uint256 private _decimals;
uint256 Rate=600000;
uint256 public basePercent = 200;
address private feeholder =0xDDC3eF96A93ee61EeeB1411dB920b60B384109f3;
address private TeamTokensAdd =0xC739Ed939f0CA124917059318b0d03d3Af3bEF9f;
address private DevelopmentTeamAdd= 0xe82e62CBeede5636A40672EdeA7E0a5690b5A4e9; //0xd9B3F34d26B614fD566ae627439D2AE9B31deEE4
address private contractAdd;
address private PreSaleTokenholder=0xDDC3eF96A93ee61EeeB1411dB920b60B384109f3;
constructor () {
_name = 'Fixed Swap Protocol';
_symbol = 'FXP';
_decimals = 18;
_totalSupply = 11000000 * (10**_decimals);
//transfer total supply to owner
_balances[contractAdd] =_totalSupply;
_balances[DevelopmentTeamAdd]=1000000e18;
_balances[TeamTokensAdd]=1000000e18;
_balances[PreSaleTokenholder]=9000000e18;
//fire an event on transfer of tokens
emit Transfer(address(this),DevelopmentTeamAdd, _balances[DevelopmentTeamAdd]);
emit Transfer(address(this),TeamTokensAdd, _balances[TeamTokensAdd]);
emit Transfer(address(this),PreSaleTokenholder, _balances[PreSaleTokenholder]);
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint256) {
return _decimals;
}
function totalSupply() public view override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view override returns (uint256) {
return _balances[account];
}
function find1Percent(uint256 value) public view returns (uint256) {
uint256 roundValue = value.ceil(basePercent);
uint256 onePercent = roundValue.mul(basePercent).div(10000);
return onePercent;
}
function transfer(address recipient, uint256 amount) public override returns (bool) {
_transfer(msg.sender, recipient, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(msg.sender, spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
require(_allowances[sender][msg.sender]>=amount,"In Sufficient allowance");
_transfer(sender, recipient, amount);
_approve(sender,msg.sender, _allowances[sender][msg.sender]-=amount);
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
require(sender != recipient,"cannot send money to your Self");
require(_balances[sender]>=amount,"In Sufficiebt Funds");
uint256 tokensToBurn = find1Percent(amount);
uint256 tokensToTransfer = amount.sub(tokensToBurn);
_balances[sender] = _balances[sender].sub(amount);
_balances[recipient] = _balances[recipient].add(tokensToTransfer);
_balances[feeholder] = _balances[feeholder].add(tokensToBurn);
emit Transfer(sender, feeholder, tokensToBurn );
emit Transfer(sender, recipient, amount);
}
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
require(owner != spender,"cannot send allowances to yourself");
require(_balances[owner]>=amount,"In Sufficiebt Funds");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function exchangeToken()public payable {
_transfer(PreSaleTokenholder,msg.sender,msg.value*Rate);
emit Transfer(PreSaleTokenholder,msg.sender, msg.value*Rate);
payable(PreSaleTokenholder).transfer(msg.value);
}
receive()
payable
external {
}
}
// Right click on the script name and hit "Run" to execute
(async () => {
try {
console.log('Running deployWithEthers script...')
const contractName = 'Storage' // Change this for other contract
const constructorArgs = [] // Put constructor args (if any) here for your contract
// Note that the script needs the ABI which is generated from the compilation artifact.
// Make sure contract is compiled and artifacts are generated
const artifactsPath = `browser/contracts/artifacts/${contractName}.json` // Change this for different path
const metadata = JSON.parse(await remix.call('fileManager', 'getFile', artifactsPath))
// 'web3Provider' is a remix global variable object
const signer = (new ethers.providers.Web3Provider(web3Provider)).getSigner()
let factory = new ethers.ContractFactory(metadata.abi, metadata.data.bytecode.object, signer);
let contract = await factory.deploy(...constructorArgs);
console.log('Contract Address: ', contract.address);
// The contract is NOT deployed yet; we must wait until it is mined
await contract.deployed()
console.log('Deployment successful.')
} catch (e) {
console.log(e.message)
}
})()
// Right click on the script name and hit "Run" to execute
(async () => {
try {
console.log('Running deployWithWeb3 script...')
const contractName = 'Storage' // Change this for other contract
const constructorArgs = [] // Put constructor args (if any) here for your contract
// Note that the script needs the ABI which is generated from the compilation artifact.
// Make sure contract is compiled and artifacts are generated
const artifactsPath = `browser/contracts/artifacts/${contractName}.json` // Change this for different path
const metadata = JSON.parse(await remix.call('fileManager', 'getFile', artifactsPath))
const accounts = await web3.eth.getAccounts()
let contract = new web3.eth.Contract(metadata.abi)
contract = contract.deploy({
data: metadata.data.bytecode.object,
arguments: constructorArgs
})
const newContractInstance = await contract.send({
from: accounts[0],
gas: 1500000,
gasPrice: '30000000000'
})
console.log('Contract deployed at address: ', newContractInstance.options.address)
} catch (e) {
console.log(e.message)
}
})()
// SPDX-License-Identifier: MIT
pragma solidity 0.8.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);
}
/*
* @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 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) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin guidelines: functions revert instead
* of returning `false` on failure. This behavior is nonetheless conventional
* and does not conflict with the expectations of ERC20 applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20 {
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The defaut value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All three of these values are immutable: they can only be set once during
* construction.
*/
constructor (string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5,05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless this function is
* overloaded;
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `recipient` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* 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) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
_approve(sender, _msgSender(), currentAllowance - amount);
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 {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender] + 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 {IERC20-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 virtual returns (bool) {
uint256 currentAllowance = _allowances[_msgSender()][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
_approve(_msgSender(), spender, currentAllowance - subtractedValue);
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 virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
_balances[sender] = senderBalance - amount;
_balances[recipient] += 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 virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += 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 virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
_balances[account] = accountBalance - amount;
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This 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 virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be to transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}
/**
* @dev Extension of {ERC20} that allows token holders to destroy both their own
* tokens and those that they have an allowance for, in a way that can be
* recognized off-chain (via event analysis).
*/
abstract contract ERC20Burnable is Context, ERC20 {
/**
* @dev Destroys `amount` tokens from the caller.
*
* See {ERC20-_burn}.
*/
function burn(uint256 amount) public virtual {
_burn(_msgSender(), amount);
}
/**
* @dev Destroys `amount` tokens from `account`, deducting from the caller's
* allowance.
*
* See {ERC20-_burn} and {ERC20-allowance}.
*
* Requirements:
*
* - the caller must have allowance for ``accounts``'s tokens of at least
* `amount`.
*/
function burnFrom(address account, uint256 amount) public virtual {
uint256 currentAllowance = allowance(account, _msgSender());
require(currentAllowance >= amount, "ERC20: burn amount exceeds allowance");
_approve(account, _msgSender(), currentAllowance - amount);
_burn(account, amount);
}
}
contract TestC is ERC20Burnable{
constructor() ERC20("TestC","TSTC"){
_mint(msg.sender,500000000000000000000);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment