So I'm trying to send some ether from a smart contract to a user, but I can't get it to compile with truffle, it does compile on remix, so I can't find the problem, everything is compiling good except this function, anyone knows what could be causing this?
function sendEther(address _to, uint _amount) public returns(bool){
require(address(this).balance >= _amount);
(bool success, bytes memory data) = payable(_to).call{value: _amount}("");
require(success, "Failed to send Ether");
return true;
}
function sellTokens(uint _amount) public{
uint etherAmount = _amount / rate;
token.transferFrom(msg.sender, address(this), _amount);
sendEther(msg.sender, etherAmount);
emit TokensSold(msg.sender, address(token), _amount, rate);
}
It throws a parse error:
expected primary expression when the call function is called.
Your message is indicating this line:
(bool success, bytes memory data) = payable(_to).call{value: _amount}("");
and it is correct syntax. The reason truffle is not compiling, you might be using an old solc version. If you do not set solc version in truffle config, I think by default truffle uses version 5.6. in your truffle.config.js
compilers: {
solc: {
// adjus tthis based on contract's solidity version
version: "0.8.4",
}
}
solidity version on contract does not need to be exactly "0.8.4". You can set it like this:
pragma solidity >=0.4.22 <0.9.0;
Related
I'm trying to implement a contract that mints NFTs to the contract and can be transfered after that.
This is my mint function:
function safeMint(address to, string memory uri) public onlyOwner {
uint256 tokenId = _tokenIdCounter.current();
_tokenIdCounter.increment();
_safeMint(address(this), tokenId);
_setTokenURI(tokenId, uri);
}
I get this error in testing:
Should set the right owner:
AssertionError: expected '0x5FbDB2315678afecb367f032d93F642f641…' to equal '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb…'
+ expected - actual
Any ideas on how to achieve this? Can I hard code the address on the mint function?
How do I fix this issue?
The 0x5f4e... address hardcoded in your getVersion() function doesn't hold any smart contract on the Kovan testnet (link). Even though it has a contract deployed on the mainnet, these environments are separated.
When there's no smart contract on the address, there's nothing to send a response to the internal call. Your code expects an uint256 response from the version() call, so that it can return it from the getVersion().
When it doesn't receive the expected response, it throws an exception, effectively reverting the "main" call.
/ SPDX-License-Identifier: MIT
pragma solidity >=0.6.6 <0.9.0;
interface AggregatorV3Interface {
function decimals()
external view returns (
uint8
);
function description()
external view returns (
string memory
);
function version()
external view returns (
uint256
);
// getRoundData and latestRoundData should both raise "No data present"
// if they do not have data to report, instead of returning unset values
// which could be misinterpreted as actual reported values.
function getRoundData(
uint80 _roundId
)
external view returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
function latestRoundData()
external view returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}
contract FundMe {
mapping(address =>uint256) public addressToAmountFunded;
function fund() public payable {
addressToAmountFunded[msg.sender] += msg.value;
//What the eth --> usd conversion rate
}
function getVersion() public view returns (uint256) {
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x8A753747A1Fa494EC906cE90E9f37563A8AF630e);
return priceFeed.version();
}
}
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x8A753747A1Fa494EC906cE90E9f37563A8AF630e);
I checked the address that u used here "0x8A753747A1Fa494EC906cE90E9f37563A8AF630e" found in 4 different chains.
Rinkeby, Kovan, Ropsten, BscScan. Looks like your metamask is connected to Kovan but contract is not deployed to Kovav. Verify which chain your contract is connected and connect to that network in Metamask
Once check the contract is selected correct, If you select AggregationV3Interface contract and deploy it throws this error, select the sol file you are working on and try XD
I'm trying to call a method from a contract that was instantiated from another contract. I use truffle console.
Here are the details: (I think you can gloss over the code, since this question is aimed at using truffle console, not fixing any bugs)
I have a contract called MyCoinSupply.sol:
pragma solidity ^0.8.0;
import "./MyCoin.sol";
contract MyCoinSupply is MyCoin("MyCoin", "MYC") // MyCoin is ERC20
{
constructor() public // gives 1000 tokens to the owner
{
_mint(msg.sender, 1000);
}
function getCoinbase() public returns (address) // for debugging purposes
{
return block.coinbase;
}
function _mintMinerReward() internal // gives 20 tokens to the miner
{
// _mint(block.coinbase, 20); // for some reason, block.coinbase is address 0
}
function _transfer(address from, address to, uint256 value) override internal
{
_mintMinerReward();
super._transfer(from, to, value);
}
}
I instantiate MyCoinSupply.sol within MyCoinDEX.sol:
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./MyCoinSupply.sol";
contract MyCoinDEX
{
IERC20 public token;
event Bought(uint256 amount);
event Sold(uint256 amount);
constructor() public
{
token = new MyCoinSupply();
}
function showSender() public view returns (address) // for debugging purposes
{
return (msg.sender);
}
function buy(uint256 amountTobuy) payable public // send ether and get tokens in exchange; 1 token == 1 ether
{
uint256 dexBalance = token.balanceOf(address(this));
require(amountTobuy > 0, "You need to send some ether");
require(amountTobuy <= dexBalance, "Not enough tokens in the reserve");
token.transfer(msg.sender, amountTobuy);
emit Bought(amountTobuy);
}
function sell(uint256 amount) public // send tokens to get ether back
{
require(amount > 0, "You need to sell at least some tokens");
uint256 allowance = token.allowance(msg.sender, address(this));
require(allowance >= amount, "Check the token allowance");
token.transferFrom(msg.sender, address(this), amount);
payable(msg.sender).transfer(amount);
emit Sold(amount);
}
}
Here's my migration for deploying contracts:
const MyCoinSupply = artifacts.require("MyCoinSupply");
const MyCoinDEX = artifacts.require("MyCoinDEX");
module.exports = function(deployer) {
deployer.deploy(MyCoinSupply);
deployer.deploy(MyCoinDEX);
};
Here's my problem:
When I try to call functions that belong to MyCoinDEX, all works well:
truffle(development)> let instance = await MyCoinDEX.deployed()
undefined
truffle(development)> instance.buy(1)
All is good here.
However, when I try the following I get an error:
truffle(development)> instance.token.balanceOf("0xE1994C1054f9c4171B8ae9a7E7a68F404c2bF829")
evalmachine.<anonymous>:0
instance.token.balanceOf("0xE1994C1054f9c4171B8ae9a7E7a68F404c2bF829")
^
Uncaught TypeError: instance.token.balanceOf is not a function
I Googled this error (I read this solution and this solution), but I didn't really stumble upon a solution. Can someone tell me how can I call token's methods from MyCoinDEX?
Thank you in advance!
I have the following contract in Solidity that was working up until I added the line
require(msg.value == mintPrice, "Not Enough Ether");
// contracts/NFT.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
contract NFT is ERC721URIStorage {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
uint256 mintPrice = 0.025 ether;
constructor() ERC721("NFT", "ITM"){}
function mint(address user, string memory tokenURI)
public
payable
returns (uint256)
{
require(msg.value == mintPrice, "Not Enough Ether");
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(user, newItemId);
_setTokenURI(newItemId, tokenURI);
return newItemId;
}
}
I have the following chai test that fails saying not enough ether, but the address I am using is a hardhat address with tons of ether in it
describe("NFT", function () {
it("Should return a transaction hash, async function", async function () {
const NFT = await ethers.getContractFactory("NFT");
const nft = await NFT.deploy();
await nft.deployed();
expect(await nft.mint('0xf3...fFb92266', "/Users/.../web3/nft-next-minter/public/test.json")).to.have.any.keys('hash');
expect(await nft.tokenURI(1)).to.equal('/Users/.../web3/nft-next-minter/public/test.json');
});
})
I am running npx hardhat test --network localhost
Not quite sure why I am getting this error, any help would be greatly appreciated.
Thanks ahead of time.
await nft.mint(
'0xf3...fFb92266',
"/Users/.../web3/nft-next-minter/public/test.json"
)
This JS snippet doesn't specify any value of the transaction, so it's sent with 0 value by default.
And since the contract is expecting the value to equal mintPrice (0.025 ether), it fails the require() condition, effectively reverting the transaction.
You can specify the value in the overrides param (docs).
await nft.mint(
'0xf3...fFb92266',
"/Users/.../web3/nft-next-minter/public/test.json",
{value: ethers.utils.parseEther('0.025')}
)
I have deployed a very basic solidity contract (pragma solidity^0.4.0) to Rinkeby. When I call the getters on my state variables, nothing is returned and I do not understand why. To compile the contract I'm using "solc": "^0.4.25"
Using Remix to test, the call to the getter works locally without issue. However, the call doesn't work on my contract on Rinkeby.
Here is my solidity code...
pragma solidity^0.4.0;
contract Contest {
address public manager;
uint public submissionCost;
uint8 public votesPerSubmission;
constructor (uint _submissionCost, uint8 _votesPerSubmission) public {
manager = msg.sender;
submissionCost = _submissionCost;
votesPerSubmission = _votesPerSubmission;
}
modifier restricted() {
require(msg.sender == manager, "Not authorized.");
_;
}
function adjustSubmissionCost(uint32 newCost) public restricted {
submissionCost = newCost;
}
function adjustVotesPerSubmission(uint8 newVotes) public restricted {
votesPerSubmission = newVotes;
}
}
The address of the deployed contract on Rinkeby is
0xacBd19113e0D8122E18DF48A320b635fB5D7Cdd0
https://rinkeby.etherscan.io/address/0xacbd19113e0d8122e18df48a320b635fb5d7cdd0
When calling any of the public variables from Remix, I expect a return value, however I only receive the message call to Contest.manager in the Remix console and nothing more.
I get the same behavior in my web3 dapp, with zero return when I try...
await Contest.methods.manager().call()