Chainlink Goerli - MustBeSubOwner Revert on RequestRandomness - ethereum

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.

Related

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
}
})
}

Deploying Uniswap v2 / Sushiswap or similar in Brownie, Hardhat or Truffle test suite

I am writing an automated test suite that needs to test functions against Uniswap v2 style automated market marker: do swaps and use different order routing. Thus, routers need to be deployed.
Are there any existing examples of how to deploy a testable Uniswap v2 style exchange in Brownie? Because Brownie is a minority of smart contract developers, are there any examples for Truffle or Hardhat?
I am also exploring the option of using a mainnet fork, but I am not sure if this operation is too expensive (slow) to be used in unit testing.
Using a local testnet allows you to control very precisely the state of the blockchain during your test. However, it will require you to deploy every contract you need manually.
A fork of the mainnet will save you from having to deploy every contract already deployed on the mainnet. However you will sacrifice control over the environment and will require a connection to a node.
I've deployed Uniswap 2V on a testnet a few times. To do it you will need the bytecode and ABI for the following contracts: UniswapV2Factory, UniswapV2Pair, UniswapV2Router02 (I suppose you want the second version of the router). The Uniswap docs explains very well how to download them from NPM. For the router to work properly you will also need to deploy a WETH contract. I suggest deploying the one from this github page.
Before running this code, just make sure that your chain is running. For hardhat run the following command:
npx hardhat node
Start by connecting your signer to your dev chain:
var provider = new ethers.providers.WebSocketProvider("ws://localhost:8545");
var signer = provider.getSigner();
Using the ethers.js library, you first deploy the factory:
const compiledUniswapFactory = require("#uniswap/v2-core/build/UniswapV2Factory.json");
var uniswapFactory = await new ethers.ContractFactory(compiledUniswapFactory.interface,compiledUniswapFactory.bytecode,signer).deploy(await signer.getAddress());
Then the WETH contract:
const compiledWETH = require("canonical-weth/build/conrtacts/WETH.json";
var WETH = await new ethers.ContractFactory(WETH.interface,WETH.bytecode,signer).deploy();
You can now deploy the router.
const compiledUniswapRouter = require("#uniswap/v2-periphery/build/UniswapV2Router02");
var router = await new ethers.ContractFactory(compiledUniswapRouter.abi,compiledUniswapRouter.bytecode,signer).deploy(uniswapFactory.address,WETH.address);
You will also need to deploy the ERC20 tokens you need (Here is an example with tokens I've written):
const compiledERC20 = require("../../../Ethereum/Ethereum/sources/ERC20.sol/Token.json");
var erc20Factory = new ethers.ContractFactory(compiledERC20.abi,compiledERC20.bytecode,signer);
var erc20_0 = await erc20Factory.deploy("1000000", "Token 0", "5", "T0");
var erc20_1 = await erc20Factory.deploy("1000000", "Token 1", "5", "T1");
The parameters of the deploy function will depend on the constructor of the token you wish to deploy.
You will also want to create pairs using the createPair method of the Uniswap factory.
uniswapFactory.createPair(erc20_0.address,erc20_1.address);
Keep in mind that in the pair the tokens will be ordered arbitrarly by the contract. ERC20_0 might not be the first of the two.
After that just wait for all the transactions to go through and you should be good to start your test.
For a quick and easy set up I would use Hardhat's mainnet fork.
Like #Xavier said, using a mainnet fork means you don't have to deploy each contract you want to interact with. If you're wanting to test your contract against multiple exchanges, this would be the easiest way. It does however require a connection to a node and therefore your unit tests will run slower.
As an example, let's say I want to test the following contract, which swaps ETH for an ERC20 token on Uniswap using the swapExactETHForTokens method.
pragma solidity ^0.6.6;
interface IUniswap {
function swapExactETHForTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline)
external
payable
returns (uint[] memory amounts);
function WETH() external pure returns (address);
}
contract UniswapTradeExample {
IUniswap uniswap;
// Pass in address of UniswapV2Router02
constructor(address _uniswap) public {
uniswap = IUniswap(_uniswap);
}
function swapExactETHForTokens(uint amountOutMin, address token) external payable {
address[] memory path = new address[](2);
path[0] = uniswap.WETH();
path[1] = token;
uniswap.swapExactETHForTokens{value: msg.value}(
amountOutMin,
path,
msg.sender,
now
);
}
}
From the Hardhat docs, the first thing to do is set up a connection to an archive node with Alchemy, which is free to use.
Once you have a url for the node, add it as a network to your hardhat.config.js file:
networks: {
hardhat: {
forking: {
url: "https://eth-mainnet.alchemyapi.io/v2/<key>",
blockNumber: 14189520
}
}
}
If you set blockNumber, Hardhat will fork off this block each time. This is recommended if you're using a test suite and want your tests to be deterministic.
Finally, here's the test class, which tests the swapExactETHForTokens in the above contract. As an example I'm swapping 1 ETH for DAI.
const { assert } = require("chai");
const { ethers } = require("hardhat");
const ERC20ABI = require('./ERC20.json');
const UNISWAPV2ROUTER02_ADDRESS = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D";
const DAI_ADDRESS = "0x6b175474e89094c44da98b954eedeac495271d0f";
describe("UniswapTradeExample", function () {
it("Swap ETH for DAI", async function () {
const provider = ethers.provider;
const [owner, addr1] = await ethers.getSigners();
const DAI = new ethers.Contract(DAI_ADDRESS, ERC20ABI, provider);
// Assert addr1 has 1000 ETH to start
addr1Balance = await provider.getBalance(addr1.address);
expectedBalance = ethers.BigNumber.from("10000000000000000000000");
assert(addr1Balance.eq(expectedBalance));
// Assert addr1 DAI balance is 0
addr1Dai = await DAI.balanceOf(addr1.address);
assert(addr1Dai.isZero());
// Deploy UniswapTradeExample
const uniswapTradeExample =
await ethers.getContractFactory("UniswapTradeExample")
.then(contract => contract.deploy(UNISWAPV2ROUTER02_ADDRESS));
await uniswapTradeExample.deployed();
// Swap 1 ETH for DAI
await uniswapTradeExample.connect(addr1).swapExactETHForTokens(
0,
DAI_ADDRESS,
{ value: ethers.utils.parseEther("1") }
);
// Assert addr1Balance contains one less ETH
expectedBalance = addr1Balance.sub(ethers.utils.parseEther("1"));
addr1Balance = await provider.getBalance(addr1.address);
assert(addr1Balance.lt(expectedBalance));
// Assert DAI balance increased
addr1Dai = await DAI.balanceOf(addr1.address);
assert(addr1Dai.gt(ethers.BigNumber.from("0")));
});
});
Note the const ERC20ABI = require('./ERC20.json'); at the top, which imports the ERC20ABI needed to fetch the DAI contract and use it's balanceOf() method.
That's all. Running npx hardhat test should show that this test passes.
The answer from Xavier Hamel set me in the right direction.
Unfortunately, Uniswap v2 and its clones cannot be recompiled and redeployed without editing the source code. This is because
Router depends on UniswapV2Library
UniswapV2Library has the initial code hash of UniswapV2Factory hardcoded in pairFor() function
Any recompilation may result in a different UniswapV2Factory and thus different hash
Router would fail to route any trades because pairFor fails because it generates an invalid pair contract address
This was a pesky problem. I ended up building the whole library and tooling to solve it: Please meet Smart contacts for testing. It is based on Sushiswap v2 repo, as their contracts were the best maintained.

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.

Web3.js getBalance always showing 0

I would like to get my ethereum wallet balance so i made an app with web3.js and an ethereum node running with go-ethereum.
I have some ethers on my wallet and the node is synced, but my balance always show 0 ether.
This is my app :
var Web3 = require('web3');
var web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));
balance = web3.eth.getBalance('0x...');
console.log(balance);
The node is started with this command :
geth --rpc --rpccorsdomain "*"
Status of the node with web3.js :
API Version : 0.19.0
Node Version : Geth/v1.7.2-stable-1db4ecdc/darwin-amd64/go1.9.1
Network Version : 1
Ethereum Version : 63
isConnected : true
{host: "http://localhost:8545", timeout: 0}
Listening : true
Peer Count : 25
{currentBlock: 4507134, highestBlock: 4507228, knownStates: 6019923, pulledStates: 6004673, startingBlock: 4506690}
When i fetch a transaction with
web3.eth.getTransaction('0x..')
I can see a transfer of some ethers on my wallet. When i check on etherscan, I still have theses ethers on my wallet, but the balance from web3.js is still returning 0.
When i check the last block :
web3.eth.getBlock("latest").number;
Or with :
web3.eth.blockNumber;
It's returning 0. It doesn't seems normal ?!
Thanks.
Geth uses "fast" sync by default. So you have to wait until it completely synced the blockchain data to get all the known state entries so it's normal to have to wait a couple of hours longer.
In your example, you can see that the highest block is 4507228 and current block is 4507134.
Which means that the blockchain data is not completelly synced but as I mentioned above this won't be enough for the node to give account balance information or give you the latest block information.
In order to get the updated balance for an account it also needs to sync the state of the blockchain, which is showing to have pulled 6004673 states already but it's still needs to fetch 15250 states to reach the number of known states of 6019923.
This might seem cumbersome but it's still faster than running a "full" sync which would fetch 10x more data, as the big difference is that it saves the state of the blockchain for every single block, while the "fast" sync only saves the latest state, hence why it won't return any values for the web3.eth module.
This code should work:
await window.ethereum.request({ method: "eth_requestAccounts"}) //open metamask
const web3 = new Web3(window.ethereum);
const accounts = await web3.eth.getAccounts();
const address = (accounts[0]);
const balance = await web3.eth.getBalance(address)
console.log(balance/1000000000000000000)