Truffle console send ETH to smartContract - solidity

I want to send some ETH to smart contract address
Test.deployed().then(function(instance) {return instance.contribute("0x1e0c326f4f24b5e9f5d42d695f48983d0a72b240", {from:web3.eth.accounts[0],value:10});})
but I always get
truffle(development)> Test.deployed().then(function(instance) {return instance.contribute("0x1e0c326f4f24b5e9f5d42d695f48983d0a72b240", {from:web3.eth.accounts[0],value:10});})
TypeError: instance.contribute is not a function
at evalmachine.<anonymous>:1:61
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
truffle(development)> truffle(development)>
I am using last version of truffle, so version 4.x
Same problem with
Test.deployed().then(function(instance) {return instance.getElements.call();})
Updated
contract MyContract Common {
function setMultisigWallet(address newMultisigWallet) public onlyOwner {
multisigWallet = newMultisigWallet;
}
function() external payable {
executeSale();
}
}

Send a transaction directly to a contract via instance.sendTransaction(). This is promisified like all available contract instance functions, and has the same API as web3.eth.sendTransaction but without the callback. The to value will be automatically filled in for you if not specified.

Related

How to test a solidity payable function with hardhat

I have the following smart contract function:
function safeMint(address to, uint256 tokenId) public onlyOwner payable {
require(msg.value >= mintPrice, "Not enough ETH to purchase NFT; check price!");
_safeMint(to, tokenId);
}
and the following test function in chai to test it.
describe("mint", () => {
it("should return true when 0.5 ethers are sent with transaction", async function () {
await contract.deployed();
const cost = ethers.utils.parseEther("0.1");
await contract.safeMint("0x65.....",1,cost
});
However the test function is not working and gives me an error on cost.
Error: "Type 'BigNumber' has no properties in common with type 'Overrides & { from?: PromiseOrValue; }'." I fail to understand where the error lies.
Try this, it's the valid syntax to send value with the call:
await contract.safeMint("0x65.....", 1, {value: cost});
I had a similar problem while testing a payable function, it kept saying 'object is not an instanceof of BigInt'. How I solved this problem and ensured testing ran smoothly was to test the balance of the receiver (in your case, the 'to' address), to make sure the balance has been updated. That is, if the safeMint function was successful during test, the 'to' address should be increased by 1.
You can test by:
const balOfToAdress = await contract.balanceOf(to.address)
expect(balOfToAddress).to.equal(1)
Note: the 'expect' above is gotten by requiring chai at the top of your code i.e.
const {expect} = require('chai')
and, you have to test specifically for the balance of 'to' address (Here, I just assumed the initial balance of mints on 'to' address is 0).

Testing ChainlinkClient callbacks - how to bypass recordChainlinkFulfillment?

I've got a Chainlink client contract which makes a DirectRequest to an oracle. The oracle does its thing and then returns the answer via the typical callback selector passed in via the ChainlinkRequest. It all works well, but I'd like to write some tests that test the callback implementation
My client contract is as follows:
contract PriceFeed is Ownable, ChainlinkClient {
function updatePrice() onlyOwner returns (bytes32 requestId) {
// makes Chainlink request specifying callback via this.requestCallback.selector
}
function requestCallback(bytes32 _requestId, uint256 _newPrice) public
recordChainlinkFulfillment(_requestId) {
price = _newPrice;
}
}
The problem arises when the test code calls requestCallback(...) and the code hits the recordChainlinkFulfillment(...) modifier. The ChainlinkClient complains that the requestId being passed in by the test below isn't in the underling private pendingRequests mapping maintained by the ChainlinkClient.
The simplified version of ChainlinkClient looks like this:
contract ChainlinkClient {
mapping(bytes32 => address) private pendingRequests;
modifier recordChainlinkFulfillment(bytes32 _requestId) {
require(msg.sender == pendingRequests[_requestId], "Source must be the oracle of the request");
delete pendingRequests[_requestId];
emit ChainlinkFulfilled(_requestId);
_;
}
}
My Foundry/Solidity test is as follows:
contract PriceFeedTest is Test {
function testInitialCallback() public {
priceFeed.requestCallback("abc123", 1000000); // fails on this line
assertEq(1000000, priceFeed.price(), "Expecting price to be 1000000");
}
}
The code fails on first line of the testInitialCallback() line with: Source must be the oracle of the request
How can I trick the ChainklinkClient into allowing my callback to get past the modifier check? AFAIK I can't access and pre-populate the private pendingRequests mapping. Is there another way?
I know that Foundry provides Cheatcodes to help in testing and there's a stdstorage cheatcode, but I'm not familiar on how to construct a call to stdstorage to override pendingRequests if thats even possible with a cheatcode.
contract PriceFeedTest is Test {
function testInitialCallback2() public {
stdstore
.target(address(priceFeed))
.sig("pendingRequests()")
.with_key("abc123")
.checked_write(address(this));
priceFeed.requestCallback("abc123", 1000000);
assertEq(1000000, priceFeed.price(), "Expecting price to be 1000000");
}
}
The above code throws the following error: No storage use detected for target
Any help would be greatly appreciated. Many thanks.
When you execute the updatePrice function in your test, you should be able to strip out the requestId from the transaction receipt event. Once you have that, you can then use it in your call to requestCallback. Check out this example unit test from the hardhat starter kit for an example of this

Burning Deployed ERC Tokens In an NFT Mint Function - Compiles, but Transaction Fails

I am very new to Solidity, and have recently been working on trying to learn the ropes. For reference, I have been using code from this video (https://www.youtube.com/watch?v=tBMk1iZa85Y) as a primer after having gone through the basic crypto zombies tutorial series.
I have been attempting to adapt the Solidity contract code presented in this video (which I had functioning just fine!) to require a Burn of a specified amount of an ERC-20 token before minting an NFT as an exercise for myself. I thought I had what should be a valid implementation which compiled in Remix, and then deployed to Rinkeby. I call the allowAccess function in Remix after deploying to Rinkeby, and that succeeds. But, when I call the mint function with the two parameters, I get: "gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending? execution reverted."
If I still send the transaction, metamask yields "Transaction xx failed! Transaction encountered an error.".
I'm positive it has to do with "require(paymentToken.transfer(burnwallet, amounttopay),"transfer Failed");", though I'm not sure what's wrong. Below is my entire contract code. I'm currently just interacting with the Chainlink contract on Rinkeby as my example, since they have a convenient token faucet.
pragma solidity ^0.8.0;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Counters.sol";
contract myNFTwithBurn is ERC721, Ownable {
address externalTokenAddress = 0x01BE23585060835E02B77ef475b0Cc51aA1e0709; //Token Type to burn on minting
uint256 amounttopay = 5; //number of these tokens to burn
IERC20 paymentToken = IERC20(externalTokenAddress); //my code: create an interface of the external token
address burnwallet = 0x000000000000000000000000000000000000dEaD; //burn wallet
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
using Strings for uint256;
// Optional mapping for token URIs
mapping (uint256 => string) private _tokenURIs;
// Base URI
string private _baseURIextended;
constructor() ERC721("NFTsWithBurn","NWB") {
}
function setBaseURI(string memory baseURI_) external onlyOwner() {
_baseURIextended = baseURI_;
}
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
_tokenURIs[tokenId] = _tokenURI;
}
function _baseURI() internal view virtual override returns (string memory) {
return _baseURIextended;
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory _tokenURI = _tokenURIs[tokenId];
string memory base = _baseURI();
// If there is no base URI, return the token URI.
if (bytes(base).length == 0) {
return _tokenURI;
}
// If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
if (bytes(_tokenURI).length > 0) {
return string(abi.encodePacked(base, _tokenURI));
}
// If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.
return string(abi.encodePacked(base, tokenId.toString()));
}
function allowAccess() public
{
paymentToken.approve(address(this), 5000000); //This is my attempt to allow the contract access to the user's external tokens, in this case Chainlink (paymentToken)
}
function mintItem(address to, string memory tokenURI)
public
onlyOwner
returns (uint256)
{
require(paymentToken.transfer(burnwallet, amounttopay),"transfer Failed"); //Try to transfer 5 chainlink to the burn wallet
_tokenIds.increment();
uint256 id = _tokenIds.current();
_mint(to, id);
_setTokenURI(id, tokenURI);
return id;
}
}
If anybody can at least point me to what I'm doing completely wrong in the code that I've added, please do! TIA!
I'm not sure why are you trying to burn link in order to mint and nft but first check if the link code does not have a require that check if the destination address is the burn address if it has then burn the link is not possible and you should use any other erc20 maybe your own erc20, also your contract probably does not have any link and if you want to transfer the link from the user you should do this in the contract paymentToken.transferFrom(msg.sender,destinationAddress,amount) and if the user previously approve your contract you will able to send the tokens, and i suppose that the purpose of the allowAccess function is to make the user approve the contract to move the tokens that will never work, the approve function let's anyone that call it approve any address to move an amount of tokens, the thing is that to know who is approving to let other to move the tokens the function use msg.sender to explain how this work take a look at this example
let's say that your contract is the contract A and the link contract is the contract B
now a user call allowAccess in the contract A, so here the msg.sender is the user because they call the function
now internally this function call approve on contract B, here the contract A is the msg.sender, because the contract is who call the function
so what allowAccess is really doing is making the contract approving itself to move their own tokens that I assume it doesn't have

“Out of Gas” while transferring ethereum from account to contract

I am using ganache to create 10 ethereum accounts. I want to transfer ethereum from one account to a smart contract. I am doing this by writing two following smart contracts in solidity;
pragma solidity >=0.4.0 <0.6.0;
contract Ether_Transfer_To{
function () external payable { //fallback function
}
function get_balance() public returns(uint){
return address(this).balance;
}
}
contract Ether_Transfer_From{
Ether_Transfer_To private the_instance;
constructor() public{
//the_instance=Ether_Transfer_To(address(this));
the_instance=new Ether_Transfer_To();
}
function get_balance() public returns(uint){
return address(this).balance;
}
function get_balance_of_instance() public returns(uint){
//return address(the_instance).balance;
return the_instance.get_balance();
}
function () external payable {
// msg.sender.send(msg.value)
address(the_instance).send(msg.value);
}
}
When I deploy the contract Ether_Transfer_From smart contract then I get its three-member functions as follows in remix;
But when I sent one 1 Wei from account to smart contract by writing 1 in the text box and clicking on a (fallback) button, then I get the following error;
transact to Ether_Transfer_From. (fallback) errored: VM Exception while
processing transaction: out of gas
I followed the answer of the same question by installing Ganache-cli 7.0.0 beta.0 by using following command;
npm install -g ganache-cli#7.0.0-beta.0
But I still get the same error. I think I am using older Ganache cli instead of Ganache-cli 7.0.0 beta.0 as it goes to C drive and I installed ganache 2.1.1 in D drive previously.
I just want to send ethereum from one account to other but I am really stuck in this out of gas Error. If there is any way to remove this error or transfer ethereum from one account to another then please let me know.
So this is what I did for one of my projects.
This snippet, deploys the compiles the solidity file and then deploys it and gets the address of the deployed contract address
const input = fs.readFileSync('Migrations.sol');
const output = solc.compile(input.toString(), 1);
const bytecode = output.contracts[':Migrations']['bytecode'];
const abi = JSON.parse(output.contracts[':Migrations'].interface);
var contract = new web3.eth.Contract(abi);
contract.deploy({
data: '0x'+bytecode,
})
.send({
from: chairPerson,
gas: 5500000,
gasPrice: '2000000000000'
})
.on('receipt', (receipt) => {
add=receipt.contractAddress;
})
Now using contract's abi, I can call methods of the deployed contract and use the following code to transfer '1.5' ether from one address to another.
contract.methods.registerRequest(fromAddress,toAddress,requestNumber).send({from:fromAddress,value : web3.utils.toWei('1.5', 'ether')}).on('transactionHash', (hashResult) => {-- some code--})
And also make the method in the solidity as payable to allow it to transfer ether, like :
function registerRequest(address requestedBy,address requestedTo,uint requestNumber) payable public{}
Refer : https://web3js.readthedocs.io/en/v1.2.0/web3-eth-contract.html#id12
Basically I used web3 api itself to transfer ether from one account
to another by calling my solidity method.
Also, check the following things :
1. While deploying, are you deploying with enough gas ? I faced this error when I was deploying the contract with less gas quantity
2. Your method in solidity should be payable

Solidity 'out of gas' exception when trying to transfer Ether

I try to transfer Ether from the contract to an address but it gives the error that the transaction is out of gas. I think it's a small problem but I can't find it. I have to specifically use solidity version 0.4.24.
The warning from Remix
The error from MetaMask
I have tried different methods, like:
address.transfer(amount);
address.send(amount);
address.call.value(amount)( );
All methods will give the same out of gas exception. and the send and call method will also give a warning that it's outdated and that I should use the transfer method.
I also tried to adjust the gas and it didn't work, I also tried the needed 2,300 for the transfer listed on the docs.
The code:
pragma solidity ^0.4.24;
contract TestContract {
function payAddress(address _address) external payable {
_address.transfer(msg.value);
}
}
If the problem is that the contract doesn't have any Ether to transfer, can it use the Ether I send with the function call? Or is the problem something else?
Thank you for reading.
edit:
I have tried to send Ether to my Contract and that works, I do have Ether on my contract now, but the function still gives the same error as before. So the problem is something else.
Current code:
pragma solidity ^0.4.24;
contract TestContract {
function() external payable { }
function payContract() public payable {}
function paySomeone(address _address, uint256 _amount) external {
_address.transfer(_amount);
}
function getBalance() public view returns (uint256) {
return address(this).balance;
}
}
The balance of the contract
The parameters I use
Same MetaMask error as before
As you can see here the balance of the contract is 10 wei, but when i try to send 9 wei it still gives the same out of gas error. I also still get the same error from Remix as before.
I also post the issue on the Stack exchange and got an answer there. The issue was my
Ganache version. I switched to the Robsten test network and it worked. I'll link the post here.
Yes. In order to send ether from contract to another address, first you must send some ether to the contract address. Take a look at this and this.