My function call is returning expensive gas cost on metamask - blockchain

To context. I want to make a contract that receives USDC and send custom tokens to the buyer. After that, in the same call, the contract forwards those USDCs to another wallet. I have done tests, and calls. When I do it through Remix, I'm able to get it working nicely, Rate works, forward funds, everything. However, once I try to call it through Metamask, it returns me a absurd amound of gas required (10 matic) to call buyTokens(). Could someone help me find if something is wrong, or should it be this expensive?
ps: With buyTokens(), we are also calling approve() from the buyer, to approve Crowdsale to take the right amount of USDC
I have two contracts to demonstrate. First, the custom token:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./ERC777P.sol";
import "./MinterRole.sol";
contract TokenMBP is ERC777P, MinterRole {
constructor(
string memory name,
string memory symbol,
address[] memory defaultOperators,
uint256 initialSupply
) ERC777P(name, symbol, defaultOperators)
{
_mint(msg.sender, initialSupply, "", "", "");
}
function mint(address account, uint256 amount, bytes memory userData, bytes memory operatorData, bytes32 proof) public onlyMinter returns (bool) {
_mint(account, amount, userData, operatorData, proof);
return true;
}
function burn(uint256 amount, bytes memory userData, bytes memory operatorData) public returns (bool) {
_burn(msg.sender, amount, userData, operatorData);
return true;
}
}
Then, the crowdsale:
pragma solidity ^0.5.0;
import "./Context.sol";
import "./IERC20.sol";
import "./StableCoin.sol";
import "./SafeMath.sol";
import "./SafeERC20.sol";
import "./ReentrancyGuard.sol";
/**
* #title Crowdsale
* #dev Crowdsale is a base contract for managing a token crowdsale,
* allowing investors to purchase tokens with ether. This contract implements
* such functionality in its most fundamental form and can be extended to provide additional
* functionality and/or custom behavior.
* The external interface represents the basic interface for purchasing tokens, and conforms
* the base architecture for crowdsales. It is *not* intended to be modified / overridden.
* The internal interface conforms the extensible and modifiable surface of crowdsales. Override
* the methods to add functionality. Consider using 'super' where appropriate to concatenate
* behavior.
*/
contract Crowdsale is Context, ReentrancyGuard {
using SafeMath for uint256;
using SafeERC20 for IERC20;
// The token being sold
IERC20 private _token;
STABLE private _stableCoin = _stableCoin;
// Address where funds are collected
address payable private _wallet;
// Contract owner address
address _owner;
// How many token units a buyer gets per usdc.
// The rate is the conversion between usdc and the smallest and indivisible token unit.
// So, if you are using a rate of 1 with a ERC20Detailed token with 3 decimals called TOK
// 1 usdc will give you 1 unit, or 0.001 TOK.
uint256 private _rate;
// Amount of usdc raised
uint256 private _usdcRaised;
/**
* Event for token purchase logging
* #param purchaser who paid for the tokens
* #param beneficiary who got the tokens
* #param value usdcs paid for purchase
* #param amount amount of tokens purchased
*/
event TokensPurchased(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
/**
* #param rate Number of token units a buyer gets per wei
* #dev The rate is the conversion between wei and the smallest and indivisible
* token unit. So, if you are using a rate of 1 with a ERC20Detailed token
* with 3 decimals called TOK, 1 wei will give you 1 unit, or 0.001 TOK.
* #param wallet Address where collected funds will be forwarded to
* #param token Address of the token being sold
*/
constructor (uint256 rate, address payable wallet, IERC20 token, address stableCoin) public {
require(rate > 0, "Crowdsale: rate is 0");
require(wallet != address(0), "Crowdsale: wallet is the zero address");
require(address(token) != address(0), "Crowdsale: token is the zero address");
require(address(stableCoin) != address(0), "Crowdsale: stable is the zero address");
_owner = _msgSender();
_rate = rate;
_wallet = wallet;
_token = token;
_stableCoin = STABLE(stableCoin);
}
modifier onlyOwner() {
require(_msgSender() == _owner, "OwnerRole: Only owner can make this change");
_;
}
/**
* #return the token being sold.
*/
function token() public view returns (IERC20) {
return _token;
}
/**
* #return the stable token being required.
*/
function stable() public view returns (STABLE) {
return _stableCoin;
}
/**
* #return the address where funds are collected.
*/
function wallet() public view returns (address payable) {
return _wallet;
}
/**
* #return the number of token units a buyer gets per wei.
*/
function rate() public view returns (uint256) {
return _rate;
}
/**
* #return the amount of wei raised.
*/
function usdcRaised() public view returns (uint256) {
return _usdcRaised;
}
/**
* #dev Change contract rate
* #param newRate New price for minimum amount of token
* #return true if rate was modifie
*/
function changeRate(uint256 newRate) public onlyOwner returns (bool) {
_rate = newRate;
return true;
}
/**
* #dev low level token purchase ***DO NOT OVERRIDE***
* This function has a non-reentrancy guard, so it shouldn't be called by
* another `nonReentrant` function.
* #param beneficiary Recipient of the token purchase
* #param tokenAmount Stable coin quantity for the purchase
*/
function buyTokens(address beneficiary, uint256 tokenAmount) public nonReentrant payable {
// calculate token amount to be created
// tokenAmount = tokenAmount * 10 ** 18;
uint256 tokens = _getTokenAmount(tokenAmount);
_preValidatePurchase(beneficiary, tokens);
// update state
_usdcRaised = _usdcRaised.add(tokenAmount);
bool stableStatus = _stableCoin.transferFrom(beneficiary, address(this), tokenAmount);
require(stableStatus, "Crowdsale: Stable token transfer failed");
_processPurchase(beneficiary, tokens);
emit TokensPurchased(_msgSender(), beneficiary, tokenAmount, tokens);
_updatePurchasingState(beneficiary, tokenAmount);
_forwardFunds(tokenAmount);
_postValidatePurchase(beneficiary, tokenAmount);
}
/**
* #dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met.
* Use `super` in contracts that inherit from Crowdsale to extend their validations.
* Example from CappedCrowdsale.sol's _preValidatePurchase method:
* super._preValidatePurchase(beneficiary, tokenAmount);
* require(weiRaised().add(tokenAmount) <= cap);
* #param beneficiary Address performing the token purchase
* #param tokenAmount Value in wei involved in the purchase
*/
function _preValidatePurchase(address beneficiary, uint256 tokenAmount) internal view {
require(beneficiary != address(0), "Crowdsale: beneficiary is the zero address");
require(tokenAmount != 0, "Crowdsale: tokenAmount is 0");
require(!(_stableCoin.balanceOf(beneficiary) < tokenAmount), "Crowdsale: Not enough balance");
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
}
/**
* #dev Validation of an executed purchase. Observe state and use revert statements to undo rollback when valid
* conditions are not met.
* #param beneficiary Address performing the token purchase
* #param weiAmount Value in wei involved in the purchase
*/
function _postValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
// solhint-disable-previous-line no-empty-blocks
}
/**
* #dev Source of tokens. Override this method to modify the way in which the crowdsale ultimately gets and sends
* its tokens.
* #param beneficiary Address performing the token purchase
* #param tokenAmount Number of tokens to be emitted
*/
function _deliverTokens(address beneficiary, uint256 tokenAmount) internal {
_token.safeTransfer(beneficiary, tokenAmount);
}
/**
* #dev Executed when a purchase has been validated and is ready to be executed. Doesn't necessarily emit/send
* tokens.
* #param beneficiary Address receiving the tokens
* #param tokenAmount Number of tokens to be purchased
*/
function _processPurchase(address beneficiary, uint256 tokenAmount) internal {
_deliverTokens(beneficiary, tokenAmount);
}
/**
* #dev Override for extensions that require an internal state to check for validity (current user contributions,
* etc.)
* #param beneficiary Address receiving the tokens
* #param weiAmount Value in wei involved in the purchase
*/
function _updatePurchasingState(address beneficiary, uint256 weiAmount) internal {
// solhint-disable-previous-line no-empty-blocks
}
/**
* #dev Override to extend the way in which ether is converted to tokens.
* #param stableCoinAmount Value in wei to be converted into tokens
* #return Number of tokens that can be purchased with the specified _weiAmount
*/
function _getTokenAmount(uint256 stableCoinAmount) internal view returns (uint256) {
return stableCoinAmount.div(_rate);
}
/**
* #dev Determines how ETH is stored/forwarded on purchases.
*/
function _forwardFunds(uint256 tokenAmount) internal returns (bool){
require(_stableCoin.transfer(_wallet, tokenAmount), "Crowdsale: Stable token transfer failed");
return true;
}
}
I used those contracts and with remix gas was as low as 0.01 matic.

Related

Filscoin smart contract written in solidity 0.8.0 is missing the terms and conditions Governing FILS ownership, holding and circulation

I was checking the source code of the new Filscoin token on etherscan.io Filscoin smart contract
It was missing all the terms and conditions Governing FILS ownership, holding and circulation:
1. FILS founders shall undertake and guarantee not to sell or swap any of their FILS crypto tokens before the elapse of two years post FILS crypto token creation. When the two years are elapsed and a founder desires to sell, send, swap or in any way dispose of his FILS crypto token, no more than 2% of FILS crypto tokens in the founder’s wallet can be sold every 45 days.
2. FILS co-founders shall undertake and guarantee not to sell, send, swap or in any way dispose of their FILS crypto tokens before the elapse of one year post FILS crypto token creation. When the one year is elapsed and a co-founder desires to sell his/her FILS crypto tokens, no more than 2.5% of FILS crypto tokens in co-founder’s wallet can be sold every 30 days. 3. No FILS holder shall be allowed to hold more than two million (2,000,000) FILS crypto tokens in circulation. This clause shall serve as an anti-whale constraint to prevent any whale maneuvers and to secure a stable FILS crypto token position as much as possible. This clause may be revisited on a yearly basis. 4. FILS shall prudently and rigorously ensure and supervise strict application of relevant rules and regulations to prevent any kind of monetary manipulation, fraud, terrorism funding or money laundering activities. 5. FILS shall maintain a market balancing policy that mitigates market fluctuations and anomalies, if needed. One factor of this policy is to destroy a considerable number of FILS crypto tokens when required and in a timely manner, provided that the total of which may not exceed 1% of FILS crypto tokens in circulation every year. 6. FILS shall accordingly ensure prompt and efficient response to market sudden movements and fluctuations to best serve and safeguard FILS holders’ interests and investments. Such practices may include repurchases of FILS crypto tokens to uplift FILS prices, when necessary. 7. On March 25, 2024, and after the passage of two years of FILS launch, LANDOUSES shall start accepting FILS crypto token as a payment method for LANDOUSES properties and operations (sell and buy). This shall include all LANDOUSES purchases operations for all its required items such as construction materials, etc
Here is a copy of the code found in 1 single file:
/**
*Submitted for verification at Etherscan.io on 2021-12-08
*/
// SPDX-License-Identifier: MIT
// File: #openzeppelin/contracts/token/ERC20/IERC20.sol
// OpenZeppelin Contracts v4.4.0 (token/ERC20/IERC20.sol)
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);
}
// File: #openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol
// OpenZeppelin Contracts v4.4.0 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
/**
* #dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* #dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* #dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* #dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
// File: #openzeppelin/contracts/utils/Context.sol
// OpenZeppelin Contracts v4.4.0 (utils/Context.sol)
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) {
return msg.data;
}
}
// File: #openzeppelin/contracts/token/ERC20/ERC20.sol
// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol)
pragma solidity ^0.8.0;
/**
* #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 Contracts guidelines: functions revert
* instead 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, IERC20Metadata {
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 default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two 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 override returns (string memory) {
return _name;
}
/**
* #dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override 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
* overridden;
*
* 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 override 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");
unchecked {
_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");
unchecked {
_approve(_msgSender(), spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* #dev Moves `amount` of tokens from `sender` to `recipient`.
*
* This 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");
unchecked {
_balances[sender] = senderBalance - amount;
}
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
_afterTokenTransfer(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:
*
* - `account` 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);
_afterTokenTransfer(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");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(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 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 Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been 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 _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
// File: contracts/token/ERC20/behaviours/ERC20Decimals.sol
pragma solidity ^0.8.0;
/**
* #title ERC20Decimals
* #dev Implementation of the ERC20Decimals. Extension of {ERC20} that adds decimals storage slot.
*/
abstract contract ERC20Decimals is ERC20 {
uint8 private immutable _decimals;
/**
* #dev Sets the value of the `decimals`. This value is immutable, it can only be
* set once during construction.
*/
constructor(uint8 decimals_) {
_decimals = decimals_;
}
function decimals() public view virtual override returns (uint8) {
return _decimals;
}
}
// File: contracts/service/ServicePayer.sol
pragma solidity ^0.8.0;
interface IPayable {
function pay(string memory serviceName) external payable;
}
/**
* #title ServicePayer
* #dev Implementation of the ServicePayer
*/
abstract contract ServicePayer {
constructor(address payable receiver, string memory serviceName) payable {
IPayable(receiver).pay{value: msg.value}(serviceName);
}
}
// File: contracts/token/ERC20/StandardERC20.sol
pragma solidity ^0.8.0;
/**
* #title StandardERC20
* #dev Implementation of the StandardERC20
*/
contract StandardERC20 is ERC20Decimals, ServicePayer {
constructor(
string memory name_,
string memory symbol_,
uint8 decimals_,
uint256 initialBalance_,
address payable feeReceiver_
) payable ERC20(name_, symbol_) ERC20Decimals(decimals_) ServicePayer(feeReceiver_, "StandardERC20") {
require(initialBalance_ > 0, "StandardERC20: supply cannot be zero");
_mint(_msgSender(), initialBalance_);
}
function decimals() public view virtual override returns (uint8) {
return super.decimals();
}
}
As i am a beginner programmer, can anyone tell me where can i find the missing terms and conditions and if they are located in another file? As i know the smart contract should contain all the rules governing the token!
Could this be a scam? Please help

I try to deploy a contract on rinkeby testnet with some eth but there is an error occurred

The error I face in remix is Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
execution reverted even if I have enough money to create a contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
// Get the latest ETH/USD price from chainlink price feed
import "#chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
contract FundMe {
// safe math library check uint256 for integer overflows
//mapping to store which address depositeded how much ETH
mapping(address => uint256) public addressToAmountFunded;
// array of addresses who deposited
address[] public funders;
//address of the owner (who deployed the contract)
address public owner;
constructor() public {
owner = msg.sender;
}
function fund() public payable {
// 18 digit number to be compared with donated amount
uint256 minimumUSD = 50 * 10 ** 18;
//is the donated amount less than 50USD?
require(getConversionRate(msg.value) >= minimumUSD, "You need to spend more ETH!");
//if not, add to mapping and funders array
addressToAmountFunded[msg.sender] += msg.value;
funders.push(msg.sender);
}
function getVersion() public view returns (uint256){
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331);
return priceFeed.version();
}
function getPrice() public view returns(uint256){
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331);
(,int256 answer,,,) = priceFeed.latestRoundData();
// ETH/USD rate in 18 digit
return uint256(answer * 10000000000);
}
function getConversionRate(uint256 ethAmount) public view returns (uint256){
uint256 ethPrice = getPrice();
uint256 ethAmountInUsd = (ethPrice * ethAmount) / 1000000000000000000;
// the actual ETH/USD conversation rate, after adjusting the extra 0s.
return ethAmountInUsd;
}
}
1)try downgrading your compiler version to 0.5
if that does not work try this
2)In remix try to increase your gas limit to probably 8000000
You need a receve/fallback function to send ETH to a contract. Try to add these to your contract code:
receive() external payable {
// React to receiving ether
}

Getting an SafeTransferFrom(STF) error even after approving spender for contract

I have created a swap contract for superfluid(https://superfluid.finance) super tokens, which swaps anySuperToken <-> anySuperToken, Essentially its just an ERC20 token with additional capabilities.
My swap contract works the following way -
To swap SuperTokenA -> SuperTokenB.
It unwraps the SuperTokenA -> TokenA, using the function downgrade.
Swaps for the desired token using uniswapV3.
Upgrades to superToken of superfluid and send the tokens back to the user.
This is my complete contract for the super token swap, the contract is also deployed on -
Rinkeby - https://rinkeby.etherscan.io/address/0xa48fe52fe42e7107c717d82dfa61cf5ff6919347
Polygon - https://polygonscan.com/address/0x0983c50085C81A7F41598Eb46a29001989102119
The same contract is deployed in both the places, I also tested the contract on Rinkeby - https://rinkeby.etherscan.io/tx/0xa896eadf0825365e2a7d9bd6c660c6f1d594935e79859657da040b7aeeefdebb where the swap is successful.
But I am getting STF error on polygon - which generally means that I have not given approval to spend the token, but I have given the approval.
These are the parameters I am using if someone wants to try it out -
_from = 0xCAa7349CEA390F89641fe306D93591f87595dc1F
_to = 0x27e1e4E6BC79D93032abef01025811B7E4727e85
amountIn = 10000000000000
amountOutMin = 0
path = [0x2791bca1f2de4661ed88a30c99a7a9449aa84174, 0x7ceb23fd6bc0add59e62ac25578270cff1b9f619]
poolFees = [500] // There is a uniswap USDC/WETH pool with 0.05% fees
The complete contract can also be found here - https://github.com/Ricochet-Exchange/ricochet-super-swap/blob/main/contracts/RexSuperSwap.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;
pragma abicoder v2;
import {ISuperToken} from "#superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid.sol";
import "#uniswap/v3-periphery/contracts/libraries/TransferHelper.sol";
import "#uniswap/swap-router-contracts/contracts/interfaces/ISwapRouter02.sol";
contract RexSuperSwap {
ISwapRouter02 public immutable swapRouter;
event SuperSwapComplete(uint256 amountOut);
constructor(ISwapRouter02 _swapRouter) {
swapRouter = _swapRouter;
}
/**
* #dev Swaps `amountIn` of `_from` SuperToken for at least `amountOutMin`
* of `_to` SuperToken through `path` with `poolFees` fees for each pair.
*
* Returns the amount of `_to` SuperToken received.
*/
function swap(
ISuperToken _from,
ISuperToken _to,
uint256 amountIn,
uint256 amountOutMin,
address[] memory path,
uint24[] memory poolFees // Example: 0.3% * 10000 = 3000
) external returns (uint256 amountOut) {
require(amountIn > 0, "Amount cannot be 0");
require(path.length > 1, "Incorrect path");
require(
poolFees.length == path.length - 1,
"Incorrect poolFees length"
);
// Step 1: Get underlying tokens and verify path
address fromBase = _from.getUnderlyingToken();
address toBase = _to.getUnderlyingToken();
require(path[0] == fromBase, "Invalid 'from' base token");
require(path[path.length - 1] == toBase, "Invalid 'to' base token");
// Step 2: Transfer SuperTokens from sender
TransferHelper.safeTransferFrom(
address(_from),
msg.sender,
address(this),
amountIn
);
// Step 3: Downgrade
_from.downgrade(amountIn);
// Step 4: Approve and Swap
// Encode the path for swap
bytes memory encodedPath;
for (uint256 i = 0; i < path.length; i++) {
if (i == path.length - 1) {
encodedPath = abi.encodePacked(encodedPath, path[i]);
} else {
encodedPath = abi.encodePacked(
encodedPath,
path[i],
poolFees[i]
);
}
}
// Approve the router to spend token supplied (fromBase).
TransferHelper.safeApprove(
fromBase,
address(swapRouter),
amountIn
);
IV3SwapRouter.ExactInputParams memory params = IV3SwapRouter
.ExactInputParams({
path: encodedPath,
recipient: address(this),
amountIn: amountIn,
amountOutMinimum: amountOutMin
});
// Execute the swap
amountOut = swapRouter.exactInput(params);
// Step 5: Upgrade and send tokens back
TransferHelper.safeApprove(address(toBase), address(_to), amountOut);
_to.upgrade(amountOut);
TransferHelper.safeApprove(address(_to), msg.sender, amountOut);
TransferHelper.safeTransferFrom(
address(_to),
address(this),
msg.sender,
amountOut
);
emit SuperSwapComplete(amountOut);
}
}

Retrieve the random number generated by Chainlink VRF in 1 transaction

I am trying to get a random number in solidity in 1 transaction with Chainlink VRF.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "#chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
contract RandomNumberConsumer is VRFConsumerBase {
bytes32 internal keyHash;
uint256 internal fee;
uint256 internal randomResult;
constructor()
VRFConsumerBase(
0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9, // VRF Coordinator
0xa36085F69e2889c224210F603D836748e7dC0088 // LINK Token
)
{
keyHash = 0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4;
fee = 0.1 * 10 ** 18; // 0.1 LINK (Varies by network)
}
function getRandomNumber() public returns (bytes32 requestId) {
require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet");
return requestRandomness(keyHash, fee);
}
function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
randomResult = randomness;
}
function letsGo() public {
bytes32 requestId;
requestId = getRandomNumber();
fulfillRandomness(requestId, 123456);
}
}
Is there a way in blockchain to get the randomResult?
I'm looking specifically at my letsGo function.
The chainlink VRF is a 2 transaction process.
The first transaction requests the random number, and the second to have the random number returned. You can't get the random number in 1 go.
You can read more about the basic request model in the documentation.
You're letsgo function will not work.

Implementing buying and selling in Solidity

So i want to be able to buy/sell the token, but also have the ability for users to send eth to my contract wallet and receive my tokens in exchange. I believe i have the code ready for buyers and sellers to make a transaction together, dont think i have the pieces for someone to recieve tokens for sending me ethereum. I would like to make it so at the start people send me eth for a number of coins set at a base value
pragma solidity 0.4.22;
contract ERC20Basic {
string public constant name = "Community Token";
string public constant symbol = "COMM";
uint8 public constant decimals = 1;
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
event Transfer(address indexed from, address indexed to, uint tokens);
mapping(address => uint256) balances;
mapping(address => mapping (address => uint256)) allowed;
uint256 totalSupply_;
using SafeMath for uint256;
constructor(uint256 total) public {
totalSupply_ = total;
balances[msg.sender] = totalSupply_;
}
function totalSupply() public view returns (uint256) {
return totalSupply_;
}
function balanceOf(address tokenOwner) public view returns (uint) {
return balances[tokenOwner];
}
function transfer(address receiver, uint numTokens) public returns (bool) {
require(numTokens <= balances[msg.sender]);
balances[msg.sender] = balances[msg.sender].sub(numTokens);
balances[receiver] = balances[receiver].add(numTokens);
emit Transfer(msg.sender, receiver, numTokens);
return true;
}
function approve(address delegate, uint numTokens) public returns (bool) {
allowed[msg.sender][delegate] = numTokens;
emit Approval(msg.sender, delegate, numTokens);
return true;
}
function allowance(address owner, address delegate) public view returns (uint) {
return allowed[owner][delegate];
}
function transferFrom(address owner, address buyer, uint numTokens) public returns (bool) {
require(numTokens <= balances[owner]);
require(numTokens <= allowed[owner][msg.sender]);
balances[owner] = balances[owner].sub(numTokens);
allowed[owner][msg.sender] = allowed[owner][msg.sender].sub(numTokens);
balances[buyer] = balances[buyer].add(numTokens);
emit Transfer(owner, buyer, numTokens);
return true;
}
}
library SafeMath {
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;
}
}
A very basic example of buy and sell:
pragma solidity ^0.8;
contract ERC20Basic{
uint256 public constant tokenPrice = 5; // 1 token for 5 wei
function buy(uint256 _amount) external payable {
// e.g. the buyer wants 100 tokens, needs to send 500 wei
require(msg.value == _amount * tokenPrice, 'Need to send exact amount of wei');
/*
* sends the requested amount of tokens
* from this contract address
* to the buyer
*/
transfer(msg.sender, _amount);
}
function sell(uint256 _amount) external {
// decrement the token balance of the seller
balances[msg.sender] -= _amount;
increment the token balance of this contract
balances[address(this)] += _amount;
/*
* don't forget to emit the transfer event
* so that external apps can reflect the transfer
*/
emit Transfer(msg.sender, address(this), _amount);
// e.g. the user is selling 100 tokens, send them 500 wei
payable(msg.sender).transfer(amount * tokenPrice);
}
}
This will allow any user to buy or sell tokens from/to your contract. Your contract will need to own these tokens in order to sell them to the users. Also your contract will need to have enough ETH in order to buy back tokens from the users.
You can expand on this code to implement
a contract owner that is authorized to change the price
different prices for buy and sell
fees
min/max amounts (per one transaction, per user, per day, ...)
calculating the amount of tokens based on the msg.value (the user won't have to have the exact amount)
etc...
Note that my snippet is using Solidity 0.8 where integer overflow is prevented automatically. The question is using deprecated Solidity 0.4, so that you'd need to use SafeMath, check the value with require/assert or upgrade to Solidity 0.8 to reach the same result.