Get deployed contract by address - solidity

According to this doc. We can use ethers.getContract to get deployed contract.
I have deployed my contract at 0x33F4623337b8F9EDc9529a79F0d68B2BeC98d5E2 and my creator address is 0x6e0F5B57FEdc8911722c92dcD5D7D0cf69ceA385 now to get contract i am doing
deployedContract = await ethers.getContract(
"0x33F4623337b8F9EDc9529a79F0d68B2BeC98d5E2",
"0x6e0F5B57FEdc8911722c92dcD5D7D0cf69ceA385"
)
But its throwing error
Error: No Contract deployed with name 0x33F4623337b8F9EDc9529a79F0d68B2BeC98d5E2
But you can see contract is deployed https://goerli.etherscan.io/address/0x33F4623337b8F9EDc9529a79F0d68B2BeC98d5E2
Can someone help me here?

It's just simple.
You can use getContractAt function.
getContractAt: <T extends ethers.Contract>(
nameOrAbi: string | any[],
address: string,
signer?: ethers.Signer | string
) => Promise<T>;
So in your case, it could be:
const raffle = await ethers.getcontractAt(
"Raffle",
"0x33F4623337b8F9EDc9529a79F0d68B2BeC98d5E2",
"0x6e0F5B57FEdc8911722c92dcD5D7D0cf69ceA385"
);
In addition, you got the error since you used the contract address for the contract name.
getContract: <T extends ethers.Contract>(
name: string,
signer?: ethers.Signer | string
) => Promise<T>;

The 0x33F4... contract is deployed on the Goerli testnet, and it's available only on this network. Your post doesn't state to which network is your ethers provider connected to, but based on the context I'm assuming it's a different network - for example the local emulated hardhat network (which is the default option if you don't specify any provider) or the Ethereum mainnet.
The getContract() function is present only in historic versions of the ethers package. Based on the documentation that you linked, it seems that you're using version 0.0.1 (and it seems that it's not a misconfiguration of the docs page, as the 0.0.1 version in fact exists). Current version (January 2023) of the package is 5.4 - you can find its docs at https://docs.ethers.io/v5/.
Second argument in the originally linked documentation is contractInterface. Which is not the deployer address (passed in your example) but an ABI (Application Binary Interface) - a JSON-formatted specification of public and external methods of the contract and its events. Example of such ABI JSON can be found in the original docs a below the Example headline.
Each contract usually has its own unique ABI that is generated from its source code during contract compilation, but you can also use generic ABI for standardized functions. For example all ERC-20 token contracts have the same functions required by the ERC-20 standard (and these functions are included in the generic ERC-20 ABI), plus they might implement some other functions on top of that (these custom functions are not in the generic ABI).
Here's an example of interacting with the contract with the current version (0.5.4) of ethers, connected to a Goerli network provider:
const { ethers } = require("ethers");
// A 3rd party provider that is connected to the Goerli network
const provider = new ethers.providers.JsonRpcProvider("https://goerli.infura.io/v3/<your_api_key>");
const CONTRACT_ADDRESS = "0x33F4623337b8F9EDc9529a79F0d68B2BeC98d5E2";
// ABI JSON of this specific contract, not included in the answer for readability
const CONTRACT_ABI = [/* ... */];
async function run() {
const myContract = new ethers.Contract(CONTRACT_ADDRESS, CONTRACT_ABI, provider);
// `getEntryFee()` function defined in the ABI JSON as well as in the actual contract
const entryFee = await myContract.getEntryFee();
console.log(entryFee.toString());
}
run();
Note: Above is a standalone NodeJS script that is not using the Hardhat framework. You can also add the network in your Hardhat config file, and then run a script from their scripts folder that automatically includes ethers and connects to the selected provider.
require("#nomicfoundation/hardhat-toolbox");
module.exports = {
solidity: "0.8.17",
networks: {
goerli: {
url: "https://goerli.infura.io/v3/<your_api_key>",
accounts: [<private_key>, <private_key>], // for sending transactions
}
}
};
npx hardhat run --network goerli scripts/myScript.js

Add this to hardhat.config.js
networks: {
goerli: {
url: `https://goerli.infura.io/v3/${process.env.INFURA_API_KEY}`,
accounts: [process.env.PRI_KEY],
},
},
create .env and add your env variables
// I am loading env variables
env $(cat .env) npx hardhat run --network goerli scripts/yourScriptFile.js

Related

How to aggregate multiple smart contract function calls on Rootstock?

I have multiple ERC20 tokens, deployed on Rootstock,
and I want to track their balances and allowances in a real time from my DApp.
In ethers.js,
I can track their balances by alternately calling the functions
balanceOf(address) and allowance(owner, spender).
However, across two tokens, that equates to about
4 JSON-RPC requests every ~30 seconds.
I would prefer to reduce the frequency of JSON-RPC requests made by my application,
by aggregating these particular requests.
Is it possible to combine multiple smart contract data queries
into a single JSON-RPC request via ethers.js or any other library?
You could take a look at #0xsequence/multicall. It consists of:
MultiCallUtils smart contract with a multiCall() function intended for making aggregated calls
JS frontend library which includes a Multicall wrapper around ethers.js provider.
Smart contract deployments:
MultiCallUtils is deployed on the Rootstock Testnet: 0xb39d1Dea1bF91Aef02484F677925904b9d6936B4
I am not sure whether it is deployed at Rootstock Mainnet or not, anyway, you can deploy it there yourself.
To make aggregated smart contract calls:
Install the npm package:
npm i #0xsequence/multicall
Import the library to your project:
const { providers } = require('#0xsequence/multicall');
Create a Rootstock Testnet configuration:
const multicallConfig = {
// RSK Testnet
31: {
// maximum number of calls to batch into a single JSON-RPC call
batchSize: 50,
// defines the time each call is held on buffer waiting for subsequent calls before aggregation, ms
timeWindow: 50,
// MultiCallUtils smart contract
contract: '0xb39d1Dea1bF91Aef02484F677925904b9d6936B4',
},
};
Wrap your ethers.js current provider with a Multicall provider:
const multicallProvider = new providers.MulticallProvider(ethersProvider, multicallConfig[31]);
Connect your token smart contracts to the Multicall provider instead of ethers.js provider to be to able make aggregated calls:
const token1 = new ethers.Contract(
token1Address,
token1ABI,
multicallProvider,
);
const token2 = ...
Now you are ready to create an aggregated call:
function makeAggregatedCall() {
const aggregatedCall = [
multicallProvider.getBalance(address),
token1.balanceOf(address),
token1.allowance(owner, spender),
token2.balanceOf(address),
token2.allowance(owner, spender),
];
[
rbtcBalance,
balance1,
allowance1,
balance2,
allowance2,
] = await Promise.all(aggregatedCall);
}
The library will attempt to send all these function calls within a single call to MultiCallUtils smart contract multiCall() function.
However if the aggregated call fails,
as a fallback,
its constituent functions calls will be called individually via the ethers.js provider.
In order to subscribe to every newly minted block, attach the makeAggregatedCall function to the ethers provider block event listener:
ethersProvider.on('block', makeAggregatedCall);
You could use the ethereum-multicall project,
which consists of:
Frontend library which connects to
Multicall3 smart contract
Smart contract deployments:
The advantage of this project is that both Rootstock Mainnet and Rootstock Testnet have the Multicall3 deployments:
Mainnet 0xcA11bde05977b3631167028862bE2a173976CA11
Testnet 0xcA11bde05977b3631167028862bE2a173976CA11
... and bonus points for the 0xca11...ca11 vanity address ;)
To make aggregated smart contract calls:
Install the npm package:
npm i ethereum-multicall
Import the library to your project:
const { Multicall } = require('ethereum-multicall');
Create Multicall instance and connect it to ethers.js provider
const multicall = new Multicall({
ethersProvider: ethersProvider,
tryAggregate: true,
});
Create aggregated call:
const aggregatedCall = [
{
reference: 'token1',
contractAddress: token1Address,
abi: token1ABI,
calls: [
{
methodName: 'balanceOf',
methodParameters: [walletAddress],
},
{
methodName: 'allowance',
methodParameters: [ownerAddress, spenderAddress],
},
],
},
{
reference: 'token2',
contractAddress: token2Address,
abi: token2ABI,
calls: [
{
methodName: 'balanceOf',
methodParameters: [walletAddress],
},
{
methodName: 'allowance',
methodParameters: [ownerAddress, spenderAddress],
},
],
},
];
const { results } = await multicall.call(aggregatedCall);
Extract the required data from the results object

How to deploy a UUPS proxy contract using ethers.js?

I have erc721 uups proxy contract with initializer as :
function initialize(address owner) public initializer {
__ERC721_init("demo", "demo");
__ERC721URIStorage_init();
__Pausable_init();
__AccessControl_init();
__ERC721Burnable_init();
__UUPSUpgradeable_init();
_grantRole(DEFAULT_ADMIN_ROLE, owner);
_grantRole(PAUSER_ROLE, owner);
_grantRole(MINTER_ROLE, owner);
_grantRole(UPGRADER_ROLE, owner);
}
Now I am writing a test case for this contract using hardhat toolbox typescript version in a hardhat project.
In my testcase I first have to deploy this contract. My code for that is
const Demo = await ethers.getContractFactory("demo");
const demo = await upgrades.deployProxy(Demo, [owner.address], {
kind: "uups",
initializer: "initialize",
});
await demo.deployed();
The error I get in running this code is at that deployment code as :
Error: types/values length mismatch (count={"types":1,"values":0}, value={"types":[{"name":"owner","type":"address","indexed":null,"components":null,"arrayLength":null,"arrayChildren":null,"baseType":"address","_isParamType":true}],"values":[]}, code=INVALID_ARGUMENT, version=abi/5.7.0)
OpenZepplin Upgrades module uses autogenerated .openzepplin folder to store network related data. In my case, I had an empty folder of .openzepplin so I deleted that folder and upon running my tests again a new .openzepplin folder with new configurations was autogenerated.
Hence the upgrade.deployProxy function which was causing issues In my case was resolved.

deploy solidity smart contract

I am learning Solidity.
I wrote solidity code using openzeppelin and compile it using solcjs.
It returns multiple bytecode for main.sol and imported other sol file.
should I deploy only bytecode for main.sol?
(main.sol bytecode contains other sol files bytecode?)
I am not a native english speaker, so please forgive me my weird english.
pragma solidity ^0.8.0;
import "./contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "./contracts/utils/Counters.sol";
import "./contracts/access/Ownable.sol";
contract Name is ERC721URIStorage,Ownable {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
constructor() ERC721("Name", "name") {}
function mint(address nftowner)
public
onlyOwner
returns(uint256)
{
uint256 newItemId = _tokenIds.current();
_mint(nftowner, newItemId);
_setTokenURI(newItemId, "https://example.com");
_tokenIds.increment();
return newItemId;
}
}
On remix select the main contract with your logic to deploy. It will deploy all the dependencies as well.
Id suggest installing the etherscan plugin and making an account on their website to get an etherscan API_KEY to verify your contracts easily.
If you're not using framework like Hardhat or truffle then use remix injected web3 it's the easiest way to deploy
To deploy a smart contract, I recommend you use either Hardhat (if your familiar with JavaScript) or Foundry/Forge (which is in Solidity)
If you want to use Hardhat, you can create a deploy script like explained here in a JS file inside the scripts folder of your project:
const hardhat = require("hardhat");
async function main() {
const Contract = await hardhat.ethers.getContractFactory("YourContract");
const contract = await Contract.deploy();
await contract.deployed();
console.log(`Contract address: ${contract.address}`);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
Then, you can run the script with this command:
npx hardhat run --network <your-network> scripts/deploy.js
And you can verify your contract on Etherscan with this command
npx hardhat verify --network <your-network> <contract-address>
Both commands require some configuration in the Hardhat config file. Check the article above or the documentation for more info!
Or check out this article if you prefer to use Foundry

deploy Openzeppelin ERC20 contract with web3JS

The openzeppelin codes of ERC20 token give error in deploying directly. Even after flattern the codes, i am unable to select contract MyToken out of many contracts.
I think i need to change some codes here:
var input = {
language: 'Solidity',
sources: {'test.sol': {content: codes}},
settings: {
outputSelection: {
'*': {
'*': ['*']
}
}
}
}
This is a compiler input. Just install truffle/hardhat, and you can compile and deploy with it. They have default input options for solc that should be enough for you, they will also take care of all the imports, which is a known pain in the butt when compiling with solc directly.

How to deploy a pre-compiled contract to hardhat node

I have a proxy contract and would like to replace the underlying implementation contract.
I already have the abi & bytecode of a smart contract(retrieved from artifacts folder), so here is what I did:
const NFTv2 = await ethers.getContractFactory(upgradedContract.abi, upgradedContract.bytecode);
contract = await upgrades.upgradeProxy(proxyContract.address, NFTv2);
It works fine, but I don't want the contract to exist in my contracts folder, so I've deleted it and run npx hardhat compile again.
Now when I try to run this deploy script again, hardhat keep throwing this error:
Error: The requested contract was not found. Make sure the source code is available for compilation
at getContractNameAndRunValidation (node_modules/#openzeppelin/upgrades-core/src/validate/query.ts:46:11)
at Object.getStorageLayout (node_modules/#openzeppelin/upgrades-core/src/validate/query.ts:54:41)
at Object.deployImpl (node_modules/#openzeppelin/hardhat-upgrades/src/utils/deploy-impl.ts:30:18)
at Proxy.upgradeProxy (node_modules/#openzeppelin/hardhat-upgrades/src/upgrade-proxy.ts:36:22)
After some try & error, it seems to be related to the cache folder, once the related metadata inside the cache folder disappeared, then this error will pop out, otherwise no.
Can someone guide me on this problem and how can I deploy contract with only abi & bytecode without leaving the contract inside the contracts folder?
Thank you! :)
Here's the code of my upgraded contract:
// SPDX-License-Identifier: Apache2.0
pragma solidity ^0.8.4;
import "#openzeppelin/contracts-upgradeable/token/ERC1155/presets/ERC1155PresetMinterPauserUpgradeable.sol";
contract Test is ERC1155PresetMinterPauserUpgradeable {
string private _uri;
event upgradeEvent(string);
function uri(uint256) public view virtual override returns (string memory) {
return string(abi.encodePacked(_uri, "/new"));
}
function seturi(string memory uri) public {
emit upgradeEvent("this is an upgraded contract");
_uri = uri;
}
}
I stumbled upon this question because I struggled with the same issue, but here is what I did in the end. Basic idea is to ignore the API extensions provided by Hardhat and use Ethers.js directly.
const allSigners = await hre.ethers.getSigners();
const deployingSigner = allSigners[0];
const factory = new ContractFactory(artifact.abi, artifact.bytecode, deployingSigner);
const contract = await factory.deploy(); // no args
await contract.deployed();
console.log("Contract deployed to: ", contract.address);