I want to get all reserve in UniswapV2 pool in one request to the EVM. Here is the code getReserve :
// SPDX-License-Identifier: MIT
// compiled with 0.8.17
pragma solidity >=0.4.22 <0.9.0;
contract IUniswapV2Pair {
function getReserves() public view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast) {}
}
contract getReserve {
function get(address[] memory _add) external view returns (uint[] memory) {
uint n = _add.length;
uint[] memory liste = new uint[](n*2);
// Define variables to store the returned values
uint112 reserve0;
uint112 reserve1;
uint32 blockTimestampLast;
for (uint i=0; i<n; i++) {
// Call the getReserves function in the other contract and store the returned values
(reserve0, reserve1, blockTimestampLast) = IUniswapV2Pair(_add[i]).getReserves();
liste[i*2] = reserve0;
liste[i*2+1] = reserve1;
}
return liste;
}
function getOnlyOne(address _add) external view returns (uint112, uint112, uint32) {
return IUniswapV2Pair(_add).getReserves();
}
}
To test that this program work well on my Ganache EVM I have created this program IUniswapV2Pair:
// SPDX-License-Identifier: MIT
// compiled with 0.8.17
pragma solidity >=0.4.22 <0.9.0;
contract IUniswapV2Pair {
function getReserves() external pure returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast) {
reserve0 = 11;
reserve1 = 12;
blockTimestampLast = 13;
return (reserve0, reserve1, blockTimestampLast);
}
}
Like I said, it is working well on my Ganache EVM. But when I deploy it on the GOERLI testnet it is not working, here is the addresss :
getReserve : 0x993305D7d90675656857c7Cd69f1CF57242D79D5
IUniswapV2Pair : 0x33e57A530F90aB2A5572E2a877161Ca644e8FC95
My Problem is to make getOnlyOne("0x33e57A530F90aB2A5572E2a877161Ca644e8FC95") working.
1 Testing code on Goerli
I have tried to connect to GOERLI via Python, here is the code :
from web3 import Web3
import json, web3
server = "https://eth-goerli.public.blastapi.io"
w3 = Web3(Web3.HTTPProvider(server))
w3.isConnected()
# Contrat intermédiaire
address = "0x993305D7d90675656857c7Cd69f1CF57242D79D5"
abi = [{"inputs":[{"internalType":"address[]","name":"_add","type":"address[]"}],"name":"get","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function","constant":true},{"inputs":[{"internalType":"address","name":"_add","type":"address"}],"name":"getOnlyOne","outputs":[{"internalType":"uint112","name":"","type":"uint112"},{"internalType":"uint112","name":"","type":"uint112"},{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function","constant":true}]
contract = w3.eth.contract(address=address, abi=abi)
contract.all_functions()
contract.functions.get(["0x33e57A530F90aB2A5572E2a877161Ca644e8FC95"]).call()
contract.functions.getOnlyOne("0x33e57A530F90aB2A5572E2a877161Ca644e8FC95").call()
I have this error web3.exceptions.ContractLogicError: execution reverted, which I don't have when I do it on Ganache.
And to make sure that it is not a problem from IUniswapV2Pair I have this code:
address = "0x33e57A530F90aB2A5572E2a877161Ca644e8FC95"
abi = [{"inputs":[],"name":"getReserves","outputs":[{"internalType":"uint112","name":"reserve0","type":"uint112"},{"internalType":"uint112","name":"reserve1","type":"uint112"},{"internalType":"uint32","name":"blockTimestampLast","type":"uint32"}],"stateMutability":"pure","type":"function","constant":true}]
contract = w3.eth.contract(address=address, abi=abi)
contract.all_functions()
contract.functions.getReserves().call()
Which return me : [11, 12, 13]
2 Testing connection between contracts
I have created 2 others easier smart contract which have been working well here it is :
// SPDX-License-Identifier: MIT
// compiled with 0.8.17
pragma solidity >=0.4.22 <0.9.0;
contract FavoriteNumber {
uint favoriteNumber;
function getFavoriteNumber() external view returns(uint) {
return favoriteNumber;
}
function setFavoriteNumber(uint _favoriteNumber) external {
favoriteNumber = _favoriteNumber;
}
}
// SPDX-License-Identifier: MIT
// compiled with 0.8.17
pragma solidity >=0.4.22 <0.9.0;
contract FavoriteNumber {
function getFavoriteNumber() public view returns(uint) {}
function setFavoriteNumber(uint _favoriteNumber) public {}
}
contract ExistingNoSet {
function getA(address _t) public view returns (uint result) {
return FavoriteNumber(_t).getFavoriteNumber();
}
function setA(address _t, uint _val) public {
FavoriteNumber(_t).setFavoriteNumber(_val);
}
}
Here is the address :
FavoriteNumber : 0x14c89b4F462C11961Bb48aD6B2008f64617CF62a
ExistingNoSet : 0x97BdDaff1a971580f99C1DB850dE5EcF4982251a
And to test the code, here is the Python program, be careful I give a private key here (don't use it outside of a testnet) :
from web3 import Web3
import json, web3
server = "https://eth-goerli.public.blastapi.io"
private_key = "df49b58fbc863c5e60fe4e64829a853c46a8a12c3310404bc2a03bfefb89f68a"
public_add = "0xb4311ad11530F735ecE2d652Cbd56D1FB8D6Efeb"
w3 = Web3(Web3.HTTPProvider(server))
w3.isConnected()
# Contrat intermédiaire
address = "0x97BdDaff1a971580f99C1DB850dE5EcF4982251a"
abi = [{"inputs":[{"internalType":"address","name":"_t","type":"address"}],"name":"getA","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function","constant":true},{"inputs":[{"internalType":"address","name":"_t","type":"address"},{"internalType":"uint256","name":"_val","type":"uint256"}],"name":"setA","outputs":[],"stateMutability":"nonpayable","type":"function"}]
contract = w3.eth.contract(address=address, abi=abi)
contract.all_functions()
contract.functions.getA("0x14c89b4F462C11961Bb48aD6B2008f64617CF62a").call() # It should return 15
txn = contract.functions.setA(
"0x14c89b4F462C11961Bb48aD6B2008f64617CF62a", 3 # You set this new number
).build_transaction({
'nonce': w3.eth.get_transaction_count(public_add),
'gas': 200000,
'gasPrice': w3.toWei('20', 'gwei')
})
signed_txn = w3.eth.account.sign_transaction(txn, private_key=private_key)
w3.eth.send_raw_transaction(signed_txn.rawTransaction)
# You have to time sleep a little bit like 1min
contract.functions.getA("0x14c89b4F462C11961Bb48aD6B2008f64617CF62a").call() # It should return 3
So this program works well.
Thank you very to have read my post until here, I hope you will be able to help me.
Related
I'm trying to call the flashLoan() function on Balancer's vault contract but I keep getting an 'execution reverted' error when I view the transaction on polygonscan mumbai.
Here's my smart contract code:
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.7;
pragma abicoder v2;
import "#balancer-labs/v2-interfaces/contracts/vault/IFlashLoanRecipient.sol";
import "#openzeppelin/contracts/utils/math/SafeMath.sol";
interface Vault {
function flashLoan(
IFlashLoanRecipient recipient,
IERC20[] memory tokens,
uint256[] memory amounts,
bytes memory userData
) external;
}
contract FlashLoanSimple is IFlashLoanRecipient {
using SafeMath for uint256;
address internal constant vaultAddr = 0xBA12222222228d8Ba445958a75a0704d566BF2C8;
Vault vault = Vault(vaultAddr);
function receiveFlashLoan(IERC20[] memory tokens,uint256[] memory amounts,uint256[] memory
feeAmounts,bytes memory userData) external override {
userData;
for (uint i = 0; i < tokens.length; i++) {
uint amountOwing = amounts[i].add(feeAmounts[i]);
if(address(this).balance >= amountOwing) {
IERC20(tokens[i]).approve(vaultAddr,amountOwing);
IERC20(tokens[i]).transfer(vaultAddr, amountOwing);
}
}
}
function executeFlashLoan(address _flTokenAddr,uint256 _flAmount) external {
IERC20 flToken = IERC20(_flTokenAddr);
IERC20[] memory flTokens = new IERC20[](1);
uint256[] memory flAmounts = new uint256[](1);
flTokens[0] = flToken;
flAmounts[0] = _flAmount ;
Vault(vaultAddr).flashLoan(IFlashLoanRecipient(address(this)),flTokens,flAmounts,"");
}
}
and here is part of my script:
const maticProvider = new ethers.providers.JsonRpcProvider("https://polygon-
mumbai.g.alchemy.com/v2/Q0iw05Ps4B9YV10FMtVUSBOzxNKVoV2x");
const private_key = "xxxxxxxxxxxxxxxxxxxxxxxx";
const signer = new ethers.Wallet(private_key, maticProvider);
const Flashloan = new ethers.Contract(flashloanAddress,FlashloanJson.abi,maticProvider);
export const flashloan = async (address: string, amountIn: BigNumber) => {
const gasPrice = await maticProvider.getGasPrice();
const tx = await Flashloan.connect(signer).executeFlashLoan(address,amountIn, {gasLimit:
15000000,gasPrice: gasPrice});
return tx;
};
Any help would be greatly appreciated, I was getting an error related to gas before, but I'm no longer getting that error after I increased the gas limit. My contract is deployed on the Polygon Mumbai network and has a balance of 3 MATIC.
The problem was that I was using the Mumbai network, it only works when deployed on the mainnet.
I have a roulette smart contract, that uses another smart contract to provide it with random numbers. The issue i'm having is during compilation, i get the error:
TypeError: Type contract IRandomNumberGenerator is not implicitly convertible to expected type address.
project:/contracts/Roulette.sol:34:29:
randomNumberGenerator = IRandomNumberGenerator(randomNumberGenerator);
I'm not exactly sure where i'm going wrong, i've seen this code used in other contracts. Here is my full code, any help would be much appreciated.
// SPDX-License-Identifier: UNLICENSED"
pragma solidity ^0.8.7;
import "#openzeppelin/contracts/token/ERC20/IERC20.sol";
import "#openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "./IRandomNumberGenerator.sol";
contract Roulette is Ownable {
using SafeERC20 for IERC20;
IERC20 public gameToken;
uint256[100] internal randomNumbers;
IRandomNumberGenerator internal randomNumberGenerator;
// ensure caller is the random number generator contract
modifier onlyRandomGenerator() {
require(msg.sender == address(randomNumberGenerator), "Only random generator");
_;
}
constructor(address tokenAddress) {
gameToken = IERC20(tokenAddress);
}
function setRandomNumberGenerator(address randomNumberGenerator) external onlyOwner {
randomNumberGenerator = IRandomNumberGenerator(randomNumberGenerator);
}
function getRandomNumber() internal onlyOwner returns (uint) {
uint result = randomNumbers[randomNumbers.length-1];
delete randomNumbers[randomNumbers.length-1];
return result;
}
function numberGenerated(uint randomNumber) external onlyRandomGenerator {
randomNumbers = expand(randomNumber);
}
// generate 100 random numbers from the random number seed
function expand(uint256 randomValue) public pure returns (uint256[] memory expandedValues) {
expandedValues = new uint256[](100);
for (uint256 i = 0; i < 100; i++) {
expandedValues[i] = uint256(keccak256(abi.encode(randomValue, i)));
}
return expandedValues;
// TODO - ensure random numbers are roulette numbers
}
}
// SPDX-License-Identifier: UNLICENSED"
pragma solidity ^0.8.7;
import "#chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
import "./IRoulette.sol";
contract RandomNumberGenerator is VRFConsumerBase {
address public roulette;
bytes32 internal keyHash;
uint256 internal fee;
uint256 internal randomResult;
// modifier to check if caller of owner is the admin
modifier onlyRoulette() {
require(msg.sender == roulette, "Caller to function is not the roulette contract");
_;
}
constructor(address _roulette)
VRFConsumerBase(
0xa555fC018435bef5A13C6c6870a9d4C11DEC329C, // VRF Coordinator
0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06 // LINK Token
)
{
keyHash = 0xcaf3c3727e033261d383b315559476f48034c13b18f8cafed4d871abe5049186;
fee = 0.1 * 10 ** 18;
roulette = _roulette;
}
function getRandomNumber() public onlyRoulette returns (bytes32 requestId) {
require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet");
return requestRandomness(keyHash, fee);
}
function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
randomResult = randomness;
IRoulette(roulette).numberGenerated(randomResult);
}
}
Found out the issue was having the same name for both the parameter and the variable.
Updated the function to:
function setRandomNumberGenerator(address _randomNumberGenerator) external onlyOwner {
randomNumberGenerator = IRandomNumberGenerator(_randomNumberGenerator);
}
I'm trying to call the getNames() function on the reverse-record ens lookup contract here, but it's reverting. This is my code:
pragma solidity ^0.8.0; pragma experimental ABIEncoderV2;
contract ENStest {
/* ENS Reverse Lookup
Ropsten: 0x72c33B247e62d0f1927E8d325d0358b8f9971C68
Rinkeby: 0x196eC7109e127A353B709a20da25052617295F6f
Goerli: 0x333Fc8f550043f239a2CF79aEd5e9cF4A20Eb41e
Mainnet: 0x3671aE578E63FdF66ad4F3E12CC0c0d71Ac7510C
*/
address public ENSReverseLookupContractAddr = address(0x196eC7109e127A353B709a20da25052617295F6f); // Rinkeby
function addrToENS(address addr) public view returns(string[] memory) {
ReverseRecords ens = ReverseRecords(ENSReverseLookupContractAddr);
return ens.getNames([addr]);
}
}
// ENS Reverse Lookup Remote Contract
abstract contract ReverseRecords {
function getNames(address[] calldata addresses) external view virtual returns (string[] memory r);
}
Anyone know what I'm doing wrong here?
Resolved
I was casting a fixed-length array to a dynamic-sized array.
(h/t https://ethereum.stackexchange.com/a/103894/25695)
Revised code:
function addrToENS(address addr) public view returns(string[] memory) {
ReverseRecords ens = ReverseRecords(ENSReverseLookupContractAddr);
address[] memory t = new address[](1);
t[0] = addr;
return ens.getNames(t);
}
My question has two parts,
I am trying to create an ERC721 token using the Openzeppelin contracts with metadata and that is enumerable. My understanding is after openzeppelin v4.0.0 they removed the ERC721Full.sol contract which included metadata and enummerable. I want to use solidity 0.8.0 and so those old contracts wont work, right? When importing and inheriting ERC721Enumerable.sol into the ERC721.sol contract, I get TypeError: Definition of base has to precede definition of derived contract
I tried just importing ERC721Enumerable.sol in my own contract, but still errors. I also tried importing the older ERC721Full.sol contract and changing all the pragma 0.5.0 to pragma 0.8.0, but it inherits like a dozen other contracts and changing all of them doesn't seem wise. I tried the same with IERC721Enumerable.sol, still errors. Any ideas? Any help would be amazing!
Second part. What's the difference between ERC__ and IERC__? What's the purpose of IERC contracts?
Thanks!!
Here's my contract (I'm following a tutorial). I import the regular ERC721 contract, inherit it. it gives me an error when I test and call the totalSupply function because there is no totalSupply function:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
contract Color is ERC721 {
string[] public colors;
mapping(string => bool) _colorExists;
constructor() ERC721("Color", "COLOR") {
}
function mint(string memory _color) public {
colors.push(_color);
uint _id = colors.length;
_mint(msg.sender, _id);
_colorExists[_color] = true;
}
}
my test script:
const Color = artifacts.require('./Color.sol')
require('chai')
.use(require('chai-as-promised'))
.should()
contract('Color', (accounts) => {
let contract
before(async () => {
contract = await Color.deployed()
})
describe('deployment', async () => {
it('deploys successfully', async () => {
contract = await Color.deployed()
const address = contract.address
console.log(address)
assert.notEqual(address, 0x0)
assert.notEqual(address,'')
assert.notEqual(address, null)
assert.notEqual(address, undefined)
})
it('has a name', async () => {
const name = await contract.name()
assert.equal(name, 'Color')
})
it('has a symbol', async () => {
const symbol = await contract.symbol()
assert.equal(symbol, 'COLOR')
})
})
describe('minting', async () => {
it('creates a new token', async () => {
const result = await contract.mint('#00CD22')
const totalSupply = await contract.totalSupply()
// SUCCESS
asert.equal(totalSupply, 1)
})
})
})
this is my error without the enumerable contract/without totalSupply
I can paste the openzeppelin contracts if you like, or link them here
I also tried this, importing ERC721Enumerable
And got this:
let me know fi you need anymore info!
thanks in advance
For the first part
An ERC721 by default does not have a totalSupply method, and that's the reason you're getting the error. The totalSupply method comes from the IERC721Enumerable, wich is an optional extension of the standard ERC721 as the documentation states. If you want your ERC721 to be enumerable just import the enumerable extension from the openzeppelin implementations for your derived contract, like so:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
contract Color is ERC721Enumerable {
string[] public colors;
mapping(string => bool) _colorExists;
constructor() ERC721("Color", "COLOR") {
}
function mint(string memory _color) public {
colors.push(_color);
uint _id = colors.length;
_mint(msg.sender, _id);
_colorExists[_color] = true;
}
}
The reason the compiler gave you the error when trying to import ERC721Enumerable is that you were tryning to import it in the Openzeppelin ERC721 implementation, but that contract had to exists prior to the ERC721Enumberable. In other words the inheritance chain is
ERC721 <-- ERC721Enumerable
What you were trying to do was
ERC721 <-- ERC721Enumerable
|_____________↑
Wich creates a circular dependency that cannot be satisfied.
For the second part
ERC contracts are like abstracts classes in every OOP programming languages (first that come to my mind and maybe most relatable are Java and C++), while IERC are interfaces; this means that while both cannot be instanciated directly (they both need the children to implement something) ERC contracts provide standard implementations for the corresponding IERC methods. This is the reason often you see contracts implement the ERC contracts and not the IERC ones.
To use the ERC271Enumerable extension you need to implement it and override some functions of ERC271, _beforeTokenTransfer and supportsInterface.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
contract Color is ERC721, ERC721Enumerable{
string[] public colors;
mapping(string => bool) _colorExists;
constructor () ERC721("Color", "COLORS") {}
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override(ERC721, ERC721Enumerable) {
super._beforeTokenTransfer(from, to, tokenId);
}
function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721Enumerable) returns (bool) {
return super.supportsInterface(interfaceId);
}
function mint(string memory _color) public{
colors.push(_color);
uint _id = colors.length;
_mint(msg.sender, _id);
_colorExists[_color] = true;
}
}
What's the difference between ERC__ and IERC__? What's the purpose of IERC contracts?
IERC is the Interface for the token contract.
ERC is the implementation of the token contract.
The importance is to make sure a Contract implementation has the right methods, with the right visibility, parameters, and return values.
I've successfully deployed the following contract on Kaleido:
pragma solidity ^0.4.0;
contract Greeter {
string public greeting;
function Greeter() {
greeting = 'Hello';
}
function setGreeting(string _greeting) public {
greeting = _greeting;
}
function greet() constant returns (string) {
return greeting;
}
}
I try to interact with the contract like so:
from web3 import Web3
from web3.providers import HTTPProvider
from solc import compile_source
from web3.contract import ConciseContract
# Solidity source code
contract_source_code = '''
pragma solidity ^0.4.0;
contract Greeter {
string public greeting;
function Greeter() {
greeting = 'Hello';
}
function setGreeting(string _greeting) public {
greeting = _greeting;
}
function greet() constant returns (string) {
return greeting;
}
}
'''
compiled_sol = compile_source(contract_source_code)
contract_interface = compiled_sol[':Greeter']
w3 = Web3(HTTPProvider("https://user:password#u0telyzine-u0od4ny83j-rpc.us-east-2.kaleido.io"))
# address from previous deployment
contract_address = Web3.toChecksumAddress("0x4c94e89d5ec3125339906109f143673f40868df2")
greeter = w3.eth.contract(
address=contract_address,
abi=contract_interface['abi'],
)
print('Default contract greeting: {}'.format(
greeter.functions.greet().call()
))
# --- this hangs ---
print('Setting the greeting to Nihao...')
tx_hash = greeter.functions.setGreeting('Nihao').transact({ 'from': w3.eth.accounts[0], 'gas': 100000})
w3.eth.waitForTransactionReceipt(tx_hash)
print('Updated contract greeting: {}'.format(
greeter.functions.greet().call()
))
reader = ConciseContract(greeter)
assert reader.greet() == "Nihao"
However, when I try to submit a transaction which calls setGreeting the transaction hangs. Viewing the Kaleido logs, I see VM in read-only mode. Mutating opcode prohibited. Also, when I visit the block explorer for my node, the transactions don't load while the blocks do.
What can I do about this read only mode?
moghadasian
I could not recreate your "VM in read-only mode" when submitting a transaction - that worked successfully.
However, I had to do a bit of investigation to get web3/python connecting to Kaleido - so I'm adding a separate answer to help others trying to get going.
Configuring HTTPS authentication to Kaleido from Python web3
On my Mac, with a default pip3 installation of web3, I found the only way to configure the Python Session with auth was to use a $HOME/.netrc file such as:
machine u0oaXXXXXX-u0c4XXXXXX-rpc.us-east-2.kaleido.io
login u0d0bxXXXX
password jA-pJdIrcRaIx7XXXXXXXXXXXXXXXXXXXXXXXXX
Configure web3 for Geth/PoA
My chain was using Geth/PoA, so I had to follow the instructions here, to install the required middleware:
http://web3py.readthedocs.io/en/stable/middleware.html#geth-style-proof-of-authority
Updated example including deployment of contract
Here is the python3 that successfully deployed and reported Updated contract greeting: Nihao.
You will need to change your HTTPProvider to the HTTPS RPC URL of your node, but without the authentication headers.
from web3 import Web3
from web3.providers import HTTPProvider
from solc import compile_source
from web3.contract import ConciseContract
from web3.middleware import geth_poa_middleware
# Solidity source code
contract_source_code = '''
pragma solidity ^0.4.0;
contract Greeter {
string public greeting;
function Greeter() {
greeting = 'Hello';
}
function setGreeting(string _greeting) public {
greeting = _greeting;
}
function greet() constant returns (string) {
return greeting;
}
}
'''
compiled_sol = compile_source(contract_source_code)
contract_interface = compiled_sol['<stdin>:Greeter']
w3 = Web3(HTTPProvider("https://u0oaXXXXXX-u0c4XXXXXX-rpc.us-east-2.kaleido.io"))
w3.middleware_stack.inject(geth_poa_middleware, layer=0)
Greeter = w3.eth.contract(abi=contract_interface['abi'], bytecode=contract_interface['bin'])
tx_hash = Greeter.constructor().transact({ 'from': w3.eth.accounts[0], 'gas': 1000000})
tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash)
print('Deployed greeter contract: {}'.format(tx_receipt.contractAddress))
# address from previous deployment
contract_address = Web3.toChecksumAddress(tx_receipt.contractAddress)
greeter = w3.eth.contract(
address=contract_address,
abi=contract_interface['abi'],
)
print('Default contract greeting: {}'.format(
greeter.functions.greet().call()
))
print('Setting the greeting to Nihao...')
tx_hash = greeter.functions.setGreeting('Nihao').transact({ 'from': w3.eth.accounts[0], 'gas': 100000})
w3.eth.waitForTransactionReceipt(tx_hash)
print('Updated contract greeting: {}'.format(
greeter.functions.greet().call()
))
reader = ConciseContract(greeter)
assert reader.greet() == "Nihao"
moghadasian,
The "VM in read-only mode" is because you are using call to interact with your Smart Contract method. So it's just calling your method in a read-only mode. You would use this to call methods on contracts that query data - without having to submit a transaction to the chain.
[edit] - the above advice is generally helpful for "VM in read-only mode", but if you're trying out python web3, you pobably want the other answer with a full working example: https://stackoverflow.com/a/51155413/4972840 [/edit]
Regards, Peter