Correct way to send money to a smart contract - ethereum

I am following the tutorials in eth-scaffold and I'm on Chapter 1.
I get this error
eth_sendRawTransaction
Contract call: <UnrecognizedContract>
Transaction: 0x6c9c91bf6e2bacd32eb560b2e1922aacec848dd0dd0d6011d695ee639d57a39c
From: 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266
To: 0x5f3f1dbd7b74c6b46e8c44f98792a1daf8d69154
Value: 0.5 ETH
Gas used: 43626 of 43653
Block #55: 0x616fa7063736af541020d99e3f6d6debad67b694c958565d85f7b958859dff97
Error: Transaction reverted without a reason
at <UnrecognizedContract>.<unknown> (0x1291be112d480055dafd8a610b7d1e203891c274)
at <UnrecognizedContract>.<unknown> (0x5f3f1dbd7b74c6b46e8c44f98792a1daf8d69154)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
I didn't think I was doing anything revolutionary -
function stake() public payable {
balances[msg.sender] += msg.value;
if (address(this).balance > threshold && block.timestamp <= deadline) {
exampleExternalContract.complete{value: address(this).balance}();
}
emit Stake(msg.sender, msg.value);
}
I know that the "if" statement is getting triggered and it's erroring before it hits the emit Stake because I see two Stake events in the UI.
What's a good way to debug this as the error message is pretty unhelpful?

Related

Chainlink Goerli - MustBeSubOwner Revert on RequestRandomness

I followed the direct funding tutorial
I am testing on goerli,
however still getting a revert (tenderly tx explorer)
It is very weird, MustBeSubowner revert.
I dont quite understand it, as msg.sender is the wrapper, and when
i check the subscription owner, it is the wrapper (subId is 1519),
so it should not revert :/
This is how i did the init on goerli:
constructor(address stateAddress) VRFV2WrapperConsumerBase(
0x326C977E6efc84E512bB9C30f76E30c160eD06FB, // LINK Token
0x708701a1DfF4f478de54383E49a627eD4852C816 // VRF Wrapper ) {
keyHash = 0x79d3d8832d904592c0bf9818b621522c988bb8b0c05cdc3b15aea1b6e8db0c15;
fee = 0.25 * 10 ** 18; // in LINK (Varies by network)
This should be ok right?
And i call then:
requestId = requestRandomness(3000000, 3, 1);
I also funded the calling contract with enough LINK
I got the params from:
https://docs.chain.link/docs/vrf/v2/direct-funding/supported-networks/#goerli-testnet
I was expecting to get a fulfillRandomWords callback, but instead got a revert on requestRandomness call.
Hello Vedran
If you compare your code with the example in Create and deploy a VRF v2 compatible contract
You are NOT initializing the
ConfirmedOwner(msg.sender) in the constructor and you must do it.

How to handle approve/allowance when using custom ERC20 token?

Suppose I want to design a game where the user places a bet (using the ERC20 token) for a coin toss, and suppose the solidity function within our game contract called to place the bet is bet(uint256 _betAmount, int256 pick).
When playing around with some code, I realized that if the bet() function contains the token.transfer() call (used to place the initial bet before simulating the coin toss), the funds would be transfered from the game contract, and not from the user, even if the caller of bet() is the user. Thus, I would need to use the token.transferFrom() function, but the user would need to set the allowance for the game contract to spend the funds on their behalf.
My question is, how could this be handled in the frontend? Is there a way for a pop-up to show up asking for permission to spend the tokens (thinking of somehting similar to metamask when executing a transaction)?
Basically the user will need to accept two transactions.
But before calling the bet function you need also to wait until the approve function is confirmed.
In a project i developed i also had to handle your exact same case and i did something like this (i used react-moralis to interact with the contract):
const handleBet = async () => {
await approve({
onSuccess: async (tx) => {
await tx.wait(1) // Wait until the transaction is mined
await bet() // Call the bet function
},
onError: () => {
console.log("error") // Handle error however you want
}
})
}

Calling ethereum smart contracts with value using web3js and galanche

I'm fairly new to Ethereum smart contracts, so this might be a stupid question, but I need someone to help me out. I've set up Galanche on my machine (MacOS 11) and written a very simple currency smart contract (I don't intend to use it as an actual currency, I just want to learn about smart contracts) using truffle.
I've compiled the contract and deployed it to my Galanche blockchain successfully.
Now, I want to interact with it using web3.js. I have set up a nodejs project and installed web3. As a first test, I ran the following script:
const Web3 = require("web3");
const fs = require("fs");
const web3 = new Web3("http://192.168.178.49:7545");
const abi = JSON.parse(
fs.readFileSync("path/to/compiled/MyCoin.json").toString()
).abi;
const MyCoin = new web3.eth.Contract(
abi,
// My contract's address
"0x3265aA0A2c3ac15D0eDd67BC0fa62A446c112F98"
);
(async () => {
console.log("Starting!");
var coinCount = await MyCoin.methods
.getTotalCoins()
.call({ from: "0x2d0616BF48214513f70236D59000F1b4f395a2Fd" });
console.log("Current registered MyCoin tokens:", coinCount);
})();
The address 0x2d0616BF48214513f70236D59000F1b4f395a2Fd is the first address displayed to me in Galanche
It works as expected and returns the default amount of coins.
Now, I want to run a method called buyMyCoin which requires a payment. I tried running:
...
MyCoin
.methods
.buyMyCoin
.send(
{
from: '0x2d0616BF48214513f70236D59000F1b4f395a2Fd',
value: some_amount_of_wei
}
);
...
I'd expect that when I run this node.js script again, the first part would tell me that there are <n> total coins, but it doesn't. It just returns the same value as the last time.
Am I doing something wrong with web3.js or is this an issue with my contract?
BTW: I didn't see any funds leave the address 0x2d0616BF48214513f70236D59000F1b4f395a2Fd in Galanche, so I'm pretty sure it's not my contract...
I expect that somewhere I'd have to sign into this address using its public key, but I can't find anything about that in the web3.js docs that isn't very ambiguous...
Edit: Here's the code for my buyMyCoin method:
...
/**
* #dev Buy MyCoin
*/
function buyMyCoin() external payable {
require(msg.value > 1 gwei, "Minimum transaction is 1 gwei"); // Not very much
uint256 amount = convert(msg.value, conversionRate, true);
balances[msg.sender].owner = payable(msg.sender);
balances[msg.sender].amount += amount;
totalCoins += amount;
}
...
turns out it was just me being stupid! I was trying to run the transaction with an outrageously low amount of ether (4 gwei) which is, of course, so small that it can't be seen in the Ganache app.
The reason I was seeing no new coins being created was because my conversion code rounded the result to 0.

Data missmatch between web3.js 1.0 and Solidity

I'm mew to Ethereum/Solidity/Web3.js. I'm trying to use web3.js web.eth.sendsendTransaction() method in order to run a function in a deployed contract on a private chain.
The function I try to execute is:
contract Matematicas{
uint256 ultimaSuma;
uint256 ultimaMultiplicacion;
uint256 contador;
uint256 factorA;
uint256 factorB;
uint256 sumandoA;
uint256 sumandoB;
bytes datosMensaje;...
function multiplica(uint256 a, uint256 b) public{
datosMensaje=msg.data;
factorA=a;
factorB=b;
ultimaMultiplicacion=(a*b);
}
...
}
I call multiplica from Mist browser runnig the following JavaScript code:
var contracAddress="0xXXXXXXXX";
var contractABI=[{"constant":false,"inputs":[{"name":"a","type":"uint256"},{"name":"b","type":"uint256"}],"name":"multiplica","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},...];
var functionABI=$.grep(contractABITercero,function(metodo,index){ return metodo.name=='multiplica';});
functionABI=abiDelaFuncion[0];
var abiByteCode= web3.eth.abi.encodeFunctionCall(functionABI,[document.getElementById('firstNumber').value,document.getElementById('secondNumber').value]);
var transactionObject={from:"0xxxxxxxxxx",to:contractAddress,data:abiByteCode, gas:10000000};
web3.eth.sendTransaction(transactionObject, function(error,hash){......});
If I set firstNumber=1000 and secondNumber=2000 then abiByteCodes happens to be:
0x38e836df00000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000007d0
0x38e836df is the sha of the fuction signature, that is correct;
03e8 is hexadecimal for 1000(firstNumber) right
07d0 is hex for 2000(secondNumber) ok
But data stored in the block chain is:
datosMensaje: 0x38e836df0000000000000000000000000000000000000000000000000000000000**9e0**3e80000000000000000000000000000000000000000000000000000000000**9e0**7d0
factorA:
8520680 (0x8203E8)
factorB:
8521680 (0x8207D0)
What am I doing wrong?
I'm using geth 1.7.3 and Mist 0.9.2 on a Windows 10 64 bit desktop.
P.S. I know there are other ways to call contract functions like instantiating the contract via new web3.eth.Contract(contractABI,contractAddress) but I'm thinking about a project that would require to use the sendTransaction() method
This is due to an error in how remix IDE shows values in the debug tab. If I recover the data from the blockchain using web3.js ver 1.0 method getStorageAt(address,key) I get the expected values.

Watching Ethereum Contract State

I want to be able to watch the state/storage of an ethereum contract and know for instance when some conditions are satisfied. For instance, one account value is greater than 200, another map has more than 30 keys, etc.
What can I use for this? Is there a SaaS platform that can be used for this purpose?
EDIT: I forgot to mention that I am NOT the owner of the contract. I simply want to watch somebody's else contract.
Events are supported for this purpose.
Event Documentation
Example:
contract SomeContract {
struct AccountData {
address account;
uint value;
}
...
event AccountValueChange(address account, uint value, bytes msg);
...
function someAction() {
AccountData accountData;
// some activity with accountData...
if (accountData.value > 200) {
AccountValueChange(accountData.address, accountData.value, "Some message");
}
}
}
You can listen for the events in your client
const someContract = web3.eth.contract(abi).at(address);
myContract.events.AccountValueChange({
filter: {//Optional event filters},
fromBlock: 0
}, function(error, event){ console.log(event); })
.on('data', function(event){
console.log(event);
})
.on('error', console.error);
EDIT: Updated client code to listen to all events instead of just a single fired event.
Short answer is that you'll have to probe the EVM yourself to make this happen and then run your own node on the network that you can monitor. There is no public project I can find that will do this, and the RPC api does not provide any way to accomplish it. I used a modified Geth binary with custom transaction filters coded in and mailgun to send me emails when my conditions were met.
Events will not solve your issue because events must be included in the contract at the time of creation.