Popular New Releases in Ethereum
go-ethereum
Osun (v1.10.16)
nushell
0.61.0 Release
openzeppelin-contracts
solidity
Version 0.8.13
web3.js
v1.7.3
Popular Libraries in Ethereum
by ethereum go
35547 LGPL-3.0
Official Go implementation of the Ethereum protocol
by ccxt javascript
24082 MIT
A JavaScript / Python / PHP cryptocurrency trading API with support for more than 100 bitcoin/altcoin exchanges
by nushell rust
18606 MIT
A new type of shell
by OpenZeppelin javascript
17136 MIT
OpenZeppelin Contracts is a library for secure smart contract development.
by ethereum c++
16189 GPL-3.0
Solidity, the Smart Contract Programming Language
by chaozh javascript
15698 Apache-2.0
收集所有区块链(BlockChain)技术开发相关资料,包括Fabric和Ethereum开发资料
by amark javascript
15597 NOASSERTION
An open source cybersecurity protocol for syncing decentralized graph data.
by ChainSafe javascript
14383 NOASSERTION
Ethereum JavaScript API
by trufflesuite typescript
13000 MIT
A tool for developing smart contracts. Crafted with the finest cacaos.
Trending New libraries in Ethereum
by scaffold-eth css
6612 MIT
🏗 forkable Ethereum dev stack focused on fast product iterations
by austintgriffith css
2880 MIT
🏗 forkable Ethereum dev stack focused on fast product iterations
by ethereum-boilerplate javascript
2329 MIT
The ultimate full-stack Ethereum Dapp Boilerplate which gives you maximum flexibility and speed. Feel free to fork and contribute. Although this repo is called "Ethereum Boilerplate" it works with any EVM system and even Solana support is coming soon! Happy BUIDL!👷♂️
by project-serum rust
1899 Apache-2.0
⚓ Solana Sealevel Framework
by tharsis go
1619 LGPL-3.0
Ethermint is a scalable and interoperable Ethereum library, built on Proof-of-Stake with fast-finality using the Cosmos SDK.
by openethereum rust
1521 NOASSERTION
The fast, light, and robust client for the Ethereum mainnet.
by zhuowei rust
1370
C++ `std::unique_ptr` that represents each object as an NFT on the Ethereum blockchain
by Uniswap typescript
1348 NOASSERTION
🦄 🦄 🦄 Core smart contracts of Uniswap v3
by binance-chain go
1343 LGPL-3.0
A Binance Smart Chain client based on the go-ethereum fork
Top Authors in Ethereum
1
96 Libraries
98814
2
76 Libraries
19716
3
51 Libraries
3253
4
46 Libraries
2899
5
42 Libraries
886
6
40 Libraries
2043
7
40 Libraries
1456
8
36 Libraries
11243
9
34 Libraries
22629
10
31 Libraries
1980
1
96 Libraries
98814
2
76 Libraries
19716
3
51 Libraries
3253
4
46 Libraries
2899
5
42 Libraries
886
6
40 Libraries
2043
7
40 Libraries
1456
8
36 Libraries
11243
9
34 Libraries
22629
10
31 Libraries
1980
Trending Kits in Ethereum
No Trending Kits are available at this moment for Ethereum
Trending Discussions on Ethereum
What is the best practice of copying from array to array in Solidity?
How to locally unit-test Chainlink's Verifiable Random Function?
Trying to run "brownie run .\scripts\deploy.py --network rinkeby" but getting a ValueError
Flutter - How to refresh a Widget on button Click?
Flag provided but not defined: -rpc
Brownie testing for reverted transactions does not work with pytest.raises() or brownie.reverts()
Solidity version to learn
ParserError: Source file requires different compiler version
How to delete an image saved in IPFS blockchain?
Is it possible to call a ERC20 function inside a ERC721 contract?
QUESTION
What is the best practice of copying from array to array in Solidity?
Asked 2022-Apr-10 at 21:23I am trying to save gas by optimize code. In a flash, however, I was wondered what is the best practice of copying from array to array in Solidity.
I present two option. One is copying by pointer (I guess) and the other is using for-loop.
TestOne.sol
1contract TestContract {
2 uint32[4] testArray;
3
4 constructor(uint32[4] memory seeds) {
5 testArray = seeds; // execution costs: 152253
6 }
7
8 function Show() public returns (uint32[4] memory) {
9 return testArray;
10 }
11}
12
TestTwo.sol
1contract TestContract {
2 uint32[4] testArray;
3
4 constructor(uint32[4] memory seeds) {
5 testArray = seeds; // execution costs: 152253
6 }
7
8 function Show() public returns (uint32[4] memory) {
9 return testArray;
10 }
11}
12contract TestContract {
13 uint32[4] testArray;
14
15 constructor(uint32[4] memory seeds) {
16 for(uint i = 0; i < 4; i++) {
17 testArray[i] = seeds[i]; // execution costs: 150792
18 }
19 }
20
21 function Show() public returns (uint32[4] memory) {
22 return testArray;
23 }
24}
25
I tested with Remix (Ethereum Online IDE), 0.8.13 Solidity Compiler with Enable optimization (200)
Discussion of test resultWe can see that, TestOne used 152253 gas for execution costs, and TestTwo used 150792 gas for execution costs.
The funny thing is that, for-loop used less gas than just assigning pointer. In my little thought, for-loop would be more assembly codes than the other. (There would be, at least, assigning uint i
, substitute 4 times, check conditions 4 times (whether i < 4
), increase i++
4 times etc.)
I suspected the "optimization" of solidity compiler. But, after doing same small experiment without "Enable optimization", it does same result that for-loop used less gas. (198846 vs. 198464)
The Question isWhy do above things happened?
What is the best practice of copying from array to array? Is there any copy function like C++'s
std::copy()
?
ANSWER
Answered 2022-Apr-10 at 21:23The best practice is copy array from memory to storage without looping over their items. However contract optimization in this example is tricky. The official documentation says as follow:
If you want the initial contract deployment to be cheaper and the later function executions to be more expensive, set it to
--optimize-runs=1
. If you expect many transactions and do not care for higher deployment cost and output size, set--optimize-runs
to a high number.
To illustrate above, consider following contracts:
1contract TestContract {
2 uint32[4] testArray;
3
4 constructor(uint32[4] memory seeds) {
5 testArray = seeds; // execution costs: 152253
6 }
7
8 function Show() public returns (uint32[4] memory) {
9 return testArray;
10 }
11}
12contract TestContract {
13 uint32[4] testArray;
14
15 constructor(uint32[4] memory seeds) {
16 for(uint i = 0; i < 4; i++) {
17 testArray[i] = seeds[i]; // execution costs: 150792
18 }
19 }
20
21 function Show() public returns (uint32[4] memory) {
22 return testArray;
23 }
24}
25// SPDX-License-Identifier: MIT
26pragma solidity 0.8.13;
27
28contract TestLoop {
29 uint32[4] testArray;
30
31 function setArrayWithLoop(uint32[4] memory array) public {
32 for(uint256 i = 0; i < array.length; i++)
33 testArray[i] = array[i];
34 }
35
36 function setArrayWithoutLoop(uint32[4] memory array) public {
37 testArray = array;
38 }
39
40 function show() public view returns (uint32[4] memory) {
41 return testArray;
42 }
43}
44
45contract NoLoop {
46 uint32[4] testArray;
47
48 constructor(uint32[4] memory array) {
49 testArray = array;
50 }
51
52 function show() public view returns (uint32[4] memory) {
53 return testArray;
54 }
55}
56
57contract Loop {
58 uint32[4] testArray;
59
60 constructor (uint32[4] memory array) {
61 for(uint256 i = 0; i < array.length; i++)
62 testArray[i] = array[i];
63 }
64
65 function show() public view returns (uint32[4] memory) {
66 return testArray;
67 }
68}
69
and script written by using brownie
:
1contract TestContract {
2 uint32[4] testArray;
3
4 constructor(uint32[4] memory seeds) {
5 testArray = seeds; // execution costs: 152253
6 }
7
8 function Show() public returns (uint32[4] memory) {
9 return testArray;
10 }
11}
12contract TestContract {
13 uint32[4] testArray;
14
15 constructor(uint32[4] memory seeds) {
16 for(uint i = 0; i < 4; i++) {
17 testArray[i] = seeds[i]; // execution costs: 150792
18 }
19 }
20
21 function Show() public returns (uint32[4] memory) {
22 return testArray;
23 }
24}
25// SPDX-License-Identifier: MIT
26pragma solidity 0.8.13;
27
28contract TestLoop {
29 uint32[4] testArray;
30
31 function setArrayWithLoop(uint32[4] memory array) public {
32 for(uint256 i = 0; i < array.length; i++)
33 testArray[i] = array[i];
34 }
35
36 function setArrayWithoutLoop(uint32[4] memory array) public {
37 testArray = array;
38 }
39
40 function show() public view returns (uint32[4] memory) {
41 return testArray;
42 }
43}
44
45contract NoLoop {
46 uint32[4] testArray;
47
48 constructor(uint32[4] memory array) {
49 testArray = array;
50 }
51
52 function show() public view returns (uint32[4] memory) {
53 return testArray;
54 }
55}
56
57contract Loop {
58 uint32[4] testArray;
59
60 constructor (uint32[4] memory array) {
61 for(uint256 i = 0; i < array.length; i++)
62 testArray[i] = array[i];
63 }
64
65 function show() public view returns (uint32[4] memory) {
66 return testArray;
67 }
68}
69from brownie import TestLoop, NoLoop, Loop, accounts
70
71def function_calls():
72 contract = TestLoop.deploy({'from': accounts[0]})
73 print('set array in loop')
74 contract.setArrayWithLoop([1, 2, 3, 4], {'from': accounts[1]})
75 print('array ', contract.show(), '\n\n')
76
77 print('set array by copy from memory to storage')
78 contract.setArrayWithoutLoop([10, 9, 8, 7], {'from': accounts[2]})
79 print('array ', contract.show(), '\n\n')
80
81def deploy_no_loop():
82 print('deploy NoLoop contract')
83 contract = NoLoop.deploy([21, 22, 23, 24], {'from': accounts[3]})
84 print('array ', contract.show(), '\n\n')
85
86def deploy_loop():
87 print('deploy Loop contract')
88 contract = Loop.deploy([31, 32, 33, 34], {'from': accounts[3]})
89 print('array ', contract.show(), '\n\n')
90
91def main():
92 function_calls()
93 deploy_no_loop()
94 deploy_loop()
95
with following brownie-config.yaml
:
1contract TestContract {
2 uint32[4] testArray;
3
4 constructor(uint32[4] memory seeds) {
5 testArray = seeds; // execution costs: 152253
6 }
7
8 function Show() public returns (uint32[4] memory) {
9 return testArray;
10 }
11}
12contract TestContract {
13 uint32[4] testArray;
14
15 constructor(uint32[4] memory seeds) {
16 for(uint i = 0; i < 4; i++) {
17 testArray[i] = seeds[i]; // execution costs: 150792
18 }
19 }
20
21 function Show() public returns (uint32[4] memory) {
22 return testArray;
23 }
24}
25// SPDX-License-Identifier: MIT
26pragma solidity 0.8.13;
27
28contract TestLoop {
29 uint32[4] testArray;
30
31 function setArrayWithLoop(uint32[4] memory array) public {
32 for(uint256 i = 0; i < array.length; i++)
33 testArray[i] = array[i];
34 }
35
36 function setArrayWithoutLoop(uint32[4] memory array) public {
37 testArray = array;
38 }
39
40 function show() public view returns (uint32[4] memory) {
41 return testArray;
42 }
43}
44
45contract NoLoop {
46 uint32[4] testArray;
47
48 constructor(uint32[4] memory array) {
49 testArray = array;
50 }
51
52 function show() public view returns (uint32[4] memory) {
53 return testArray;
54 }
55}
56
57contract Loop {
58 uint32[4] testArray;
59
60 constructor (uint32[4] memory array) {
61 for(uint256 i = 0; i < array.length; i++)
62 testArray[i] = array[i];
63 }
64
65 function show() public view returns (uint32[4] memory) {
66 return testArray;
67 }
68}
69from brownie import TestLoop, NoLoop, Loop, accounts
70
71def function_calls():
72 contract = TestLoop.deploy({'from': accounts[0]})
73 print('set array in loop')
74 contract.setArrayWithLoop([1, 2, 3, 4], {'from': accounts[1]})
75 print('array ', contract.show(), '\n\n')
76
77 print('set array by copy from memory to storage')
78 contract.setArrayWithoutLoop([10, 9, 8, 7], {'from': accounts[2]})
79 print('array ', contract.show(), '\n\n')
80
81def deploy_no_loop():
82 print('deploy NoLoop contract')
83 contract = NoLoop.deploy([21, 22, 23, 24], {'from': accounts[3]})
84 print('array ', contract.show(), '\n\n')
85
86def deploy_loop():
87 print('deploy Loop contract')
88 contract = Loop.deploy([31, 32, 33, 34], {'from': accounts[3]})
89 print('array ', contract.show(), '\n\n')
90
91def main():
92 function_calls()
93 deploy_no_loop()
94 deploy_loop()
95compiler:
96 solc:
97 version: 0.8.13
98 optimizer:
99 enabled: true
100 runs: 1
101
which gives following outputs:
1contract TestContract {
2 uint32[4] testArray;
3
4 constructor(uint32[4] memory seeds) {
5 testArray = seeds; // execution costs: 152253
6 }
7
8 function Show() public returns (uint32[4] memory) {
9 return testArray;
10 }
11}
12contract TestContract {
13 uint32[4] testArray;
14
15 constructor(uint32[4] memory seeds) {
16 for(uint i = 0; i < 4; i++) {
17 testArray[i] = seeds[i]; // execution costs: 150792
18 }
19 }
20
21 function Show() public returns (uint32[4] memory) {
22 return testArray;
23 }
24}
25// SPDX-License-Identifier: MIT
26pragma solidity 0.8.13;
27
28contract TestLoop {
29 uint32[4] testArray;
30
31 function setArrayWithLoop(uint32[4] memory array) public {
32 for(uint256 i = 0; i < array.length; i++)
33 testArray[i] = array[i];
34 }
35
36 function setArrayWithoutLoop(uint32[4] memory array) public {
37 testArray = array;
38 }
39
40 function show() public view returns (uint32[4] memory) {
41 return testArray;
42 }
43}
44
45contract NoLoop {
46 uint32[4] testArray;
47
48 constructor(uint32[4] memory array) {
49 testArray = array;
50 }
51
52 function show() public view returns (uint32[4] memory) {
53 return testArray;
54 }
55}
56
57contract Loop {
58 uint32[4] testArray;
59
60 constructor (uint32[4] memory array) {
61 for(uint256 i = 0; i < array.length; i++)
62 testArray[i] = array[i];
63 }
64
65 function show() public view returns (uint32[4] memory) {
66 return testArray;
67 }
68}
69from brownie import TestLoop, NoLoop, Loop, accounts
70
71def function_calls():
72 contract = TestLoop.deploy({'from': accounts[0]})
73 print('set array in loop')
74 contract.setArrayWithLoop([1, 2, 3, 4], {'from': accounts[1]})
75 print('array ', contract.show(), '\n\n')
76
77 print('set array by copy from memory to storage')
78 contract.setArrayWithoutLoop([10, 9, 8, 7], {'from': accounts[2]})
79 print('array ', contract.show(), '\n\n')
80
81def deploy_no_loop():
82 print('deploy NoLoop contract')
83 contract = NoLoop.deploy([21, 22, 23, 24], {'from': accounts[3]})
84 print('array ', contract.show(), '\n\n')
85
86def deploy_loop():
87 print('deploy Loop contract')
88 contract = Loop.deploy([31, 32, 33, 34], {'from': accounts[3]})
89 print('array ', contract.show(), '\n\n')
90
91def main():
92 function_calls()
93 deploy_no_loop()
94 deploy_loop()
95compiler:
96 solc:
97 version: 0.8.13
98 optimizer:
99 enabled: true
100 runs: 1
101Running 'scripts/test_loop.py::main'...
102Transaction sent: 0x8380ef4abff179f08ba9704826fc44961d212e5ee10952ed3904b5ec7828c928
103 Gas price: 0.0 gwei Gas limit: 12000000 Nonce: 0
104 TestLoop.constructor confirmed Block: 1 Gas used: 251810 (2.10%)
105 TestLoop deployed at: 0x3194cBDC3dbcd3E11a07892e7bA5c3394048Cc87
106
107set array in loop
108Transaction sent: 0xfe72d6c878a980a9eeefee1dccdd0fe8214ee4772ab68ff0ac2b72708b7ab946
109 Gas price: 0.0 gwei Gas limit: 12000000 Nonce: 0
110 TestLoop.setArrayWithLoop confirmed Block: 2 Gas used: 49454 (0.41%)
111
112array (1, 2, 3, 4)
113
114
115set array by copy from memory to storage
116Transaction sent: 0x0106d1a7e37b155993a6d32d5cc9dc67696a55acd1cf29d2ed9dba0770436b98
117 Gas price: 0.0 gwei Gas limit: 12000000 Nonce: 0
118 TestLoop.setArrayWithoutLoop confirmed Block: 3 Gas used: 41283 (0.34%)
119
120array (10, 9, 8, 7)
121
122
123deploy NoLoop contract
124Transaction sent: 0x55ddded68300bb8f11b3b43580c58fed3431a2823bf3f82f0081c7bfce66f34d
125 Gas price: 0.0 gwei Gas limit: 12000000 Nonce: 0
126 NoLoop.constructor confirmed Block: 4 Gas used: 160753 (1.34%)
127 NoLoop deployed at: 0x7CA3dB74F7b6cd8D6Db1D34dEc2eA3c89a3417ec
128
129array (21, 22, 23, 24)
130
131
132deploy Loop contract
133Transaction sent: 0x1aa64f2cd527983df84cfdca5cfd7a281ff904cca227629ec8b0b29db561c043
134 Gas price: 0.0 gwei Gas limit: 12000000 Nonce: 1
135 Loop.constructor confirmed Block: 5 Gas used: 153692 (1.28%)
136 Loop deployed at: 0x2fb0fE4F05B7C8576F60A5BEEE35c23632Dc0C27
137
138array (31, 32, 33, 34)
139
- When we consider contract function call optimization, then usage of memory to storage copy, here is more info, is more gas efficient than copy by for loop. Compare
gas used
from functionsetArrayWithoutLoop
and functionsetArrayWithLoop
. - When we consider contract deployment optimization it seems there is opposite situation to this in conclusion 1.
- Most important: Contract constructor is called only once in contract lifetime, just when the contract is deployed to chain. So the most often there is an function call optimization rather than contract deployment optimization. This leads to conclusion 1.
QUESTION
How to locally unit-test Chainlink's Verifiable Random Function?
Asked 2022-Mar-08 at 04:12While trying to set up a basic self-hosted unit testing environment (and CI) that tests this Chainlink VRF random number contract, I am experiencing slight difficulties in how to simulate any relevant blockchains/testnets locally.
For example, I found this repository that tests Chainlinks VRF. However, for default deployment it suggests/requires a free KOVAN_RPC_URL
e.g. from Infura's site and even for "local deployment" it suggests/requires a free MAINNET_RPC_URL
from e.g. Alchemy's site.
I adopted a unit test environment from the waffle framework which is described as:
Filestructure1src____AmIRichAlready.sol
2 |____RandomNumberConsumer.sol
3 |
4test____AmIRichAlready.test.ts
5 |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10
AmIRichAlready.sol
1src____AmIRichAlready.sol
2 |____RandomNumberConsumer.sol
3 |
4test____AmIRichAlready.test.ts
5 |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13 function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17 IERC20 private tokenContract;
18 uint public richness = 1000000 * 10 ** 18;
19
20 constructor (IERC20 _tokenContract) public {
21 tokenContract = _tokenContract;
22 }
23
24 function check() public view returns (bool) {
25 uint balance = tokenContract.balanceOf(msg.sender);
26 return balance > richness;
27 }
28
29 // IS THIS NEEDED???
30 function setRichness(uint256 _richness) public {
31 richness = _richness;
32 }
33}
34
The RandomNumberConsumer.sol
filecontent is already on stackexange over here.
AmIRichAlready.test.ts
1src____AmIRichAlready.sol
2 |____RandomNumberConsumer.sol
3 |
4test____AmIRichAlready.test.ts
5 |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13 function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17 IERC20 private tokenContract;
18 uint public richness = 1000000 * 10 ** 18;
19
20 constructor (IERC20 _tokenContract) public {
21 tokenContract = _tokenContract;
22 }
23
24 function check() public view returns (bool) {
25 uint balance = tokenContract.balanceOf(msg.sender);
26 return balance > richness;
27 }
28
29 // IS THIS NEEDED???
30 function setRichness(uint256 _richness) public {
31 richness = _richness;
32 }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44 let mockERC20: Contract;
45 let contract: Contract;
46 let vrfContract: Contract;
47 let wallet: Wallet;
48
49 beforeEach(async () => {
50 [wallet] = new MockProvider().getWallets();
51 mockERC20 = await deployMockContract(wallet, IERC20.abi);
52 contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53 vrfContract = await deployContract(wallet, RandomNumberConsumer);
54 });
55
56 it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57 await mockERC20.mock.balanceOf
58 .withArgs(wallet.address)
59 .returns(utils.parseEther('999999'));
60 await contract.check();
61 expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62 });
63
64 it('returns false if the wallet has less than 1000000 coins', async () => {
65 await mockERC20.mock.balanceOf
66 .withArgs(wallet.address)
67 .returns(utils.parseEther('999999'));
68 expect(await contract.check()).to.be.equal(false);
69 });
70
71 it('returns true if the wallet has at least 1000000 coins', async () => {
72 await mockERC20.mock.balanceOf
73 .withArgs(wallet.address)
74 .returns(utils.parseEther('1000000'));
75 expect(await contract.check()).to.be.equal(false);
76 });
77});
78
mocha.opts
1src____AmIRichAlready.sol
2 |____RandomNumberConsumer.sol
3 |
4test____AmIRichAlready.test.ts
5 |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13 function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17 IERC20 private tokenContract;
18 uint public richness = 1000000 * 10 ** 18;
19
20 constructor (IERC20 _tokenContract) public {
21 tokenContract = _tokenContract;
22 }
23
24 function check() public view returns (bool) {
25 uint balance = tokenContract.balanceOf(msg.sender);
26 return balance > richness;
27 }
28
29 // IS THIS NEEDED???
30 function setRichness(uint256 _richness) public {
31 richness = _richness;
32 }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44 let mockERC20: Contract;
45 let contract: Contract;
46 let vrfContract: Contract;
47 let wallet: Wallet;
48
49 beforeEach(async () => {
50 [wallet] = new MockProvider().getWallets();
51 mockERC20 = await deployMockContract(wallet, IERC20.abi);
52 contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53 vrfContract = await deployContract(wallet, RandomNumberConsumer);
54 });
55
56 it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57 await mockERC20.mock.balanceOf
58 .withArgs(wallet.address)
59 .returns(utils.parseEther('999999'));
60 await contract.check();
61 expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62 });
63
64 it('returns false if the wallet has less than 1000000 coins', async () => {
65 await mockERC20.mock.balanceOf
66 .withArgs(wallet.address)
67 .returns(utils.parseEther('999999'));
68 expect(await contract.check()).to.be.equal(false);
69 });
70
71 it('returns true if the wallet has at least 1000000 coins', async () => {
72 await mockERC20.mock.balanceOf
73 .withArgs(wallet.address)
74 .returns(utils.parseEther('1000000'));
75 expect(await contract.check()).to.be.equal(false);
76 });
77});
78-r ts-node/register/transpile-only
79--timeout 50000
80--no-warnings
81test/**/*.test.{js,ts}
82
package.json
1src____AmIRichAlready.sol
2 |____RandomNumberConsumer.sol
3 |
4test____AmIRichAlready.test.ts
5 |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13 function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17 IERC20 private tokenContract;
18 uint public richness = 1000000 * 10 ** 18;
19
20 constructor (IERC20 _tokenContract) public {
21 tokenContract = _tokenContract;
22 }
23
24 function check() public view returns (bool) {
25 uint balance = tokenContract.balanceOf(msg.sender);
26 return balance > richness;
27 }
28
29 // IS THIS NEEDED???
30 function setRichness(uint256 _richness) public {
31 richness = _richness;
32 }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44 let mockERC20: Contract;
45 let contract: Contract;
46 let vrfContract: Contract;
47 let wallet: Wallet;
48
49 beforeEach(async () => {
50 [wallet] = new MockProvider().getWallets();
51 mockERC20 = await deployMockContract(wallet, IERC20.abi);
52 contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53 vrfContract = await deployContract(wallet, RandomNumberConsumer);
54 });
55
56 it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57 await mockERC20.mock.balanceOf
58 .withArgs(wallet.address)
59 .returns(utils.parseEther('999999'));
60 await contract.check();
61 expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62 });
63
64 it('returns false if the wallet has less than 1000000 coins', async () => {
65 await mockERC20.mock.balanceOf
66 .withArgs(wallet.address)
67 .returns(utils.parseEther('999999'));
68 expect(await contract.check()).to.be.equal(false);
69 });
70
71 it('returns true if the wallet has at least 1000000 coins', async () => {
72 await mockERC20.mock.balanceOf
73 .withArgs(wallet.address)
74 .returns(utils.parseEther('1000000'));
75 expect(await contract.check()).to.be.equal(false);
76 });
77});
78-r ts-node/register/transpile-only
79--timeout 50000
80--no-warnings
81test/**/*.test.{js,ts}
82{
83 "name": "example-dynamic-mocking-and-testing-calls",
84 "version": "1.0.0",
85 "main": "index.js",
86 "license": "MIT",
87 "scripts": {
88 "test": "export NODE_ENV=test && mocha",
89 "build": "waffle",
90 "lint": "eslint '{src,test}/**/*.ts'",
91 "lint:fix": "eslint --fix '{src,test}/**/*.ts'"
92 },
93 "devDependencies": {
94 "@openzeppelin/contracts": "^4.3.1",
95 "@types/chai": "^4.2.3",
96 "@types/mocha": "^5.2.7",
97 "@typescript-eslint/eslint-plugin": "^2.30.0",
98 "@typescript-eslint/parser": "^2.30.0",
99 "chai": "^4.3.4",
100 "eslint": "^6.8.0",
101 "eslint-plugin-import": "^2.20.2",
102 "ethereum-waffle": "^3.4.0",
103 "ethers": "^5.0.17",
104 "mocha": "^7.2.0",
105 "ts-node": "^8.9.1",
106 "typescript": "^3.8.3"
107 }
108}
109
tsconfig.json
1src____AmIRichAlready.sol
2 |____RandomNumberConsumer.sol
3 |
4test____AmIRichAlready.test.ts
5 |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13 function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17 IERC20 private tokenContract;
18 uint public richness = 1000000 * 10 ** 18;
19
20 constructor (IERC20 _tokenContract) public {
21 tokenContract = _tokenContract;
22 }
23
24 function check() public view returns (bool) {
25 uint balance = tokenContract.balanceOf(msg.sender);
26 return balance > richness;
27 }
28
29 // IS THIS NEEDED???
30 function setRichness(uint256 _richness) public {
31 richness = _richness;
32 }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44 let mockERC20: Contract;
45 let contract: Contract;
46 let vrfContract: Contract;
47 let wallet: Wallet;
48
49 beforeEach(async () => {
50 [wallet] = new MockProvider().getWallets();
51 mockERC20 = await deployMockContract(wallet, IERC20.abi);
52 contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53 vrfContract = await deployContract(wallet, RandomNumberConsumer);
54 });
55
56 it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57 await mockERC20.mock.balanceOf
58 .withArgs(wallet.address)
59 .returns(utils.parseEther('999999'));
60 await contract.check();
61 expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62 });
63
64 it('returns false if the wallet has less than 1000000 coins', async () => {
65 await mockERC20.mock.balanceOf
66 .withArgs(wallet.address)
67 .returns(utils.parseEther('999999'));
68 expect(await contract.check()).to.be.equal(false);
69 });
70
71 it('returns true if the wallet has at least 1000000 coins', async () => {
72 await mockERC20.mock.balanceOf
73 .withArgs(wallet.address)
74 .returns(utils.parseEther('1000000'));
75 expect(await contract.check()).to.be.equal(false);
76 });
77});
78-r ts-node/register/transpile-only
79--timeout 50000
80--no-warnings
81test/**/*.test.{js,ts}
82{
83 "name": "example-dynamic-mocking-and-testing-calls",
84 "version": "1.0.0",
85 "main": "index.js",
86 "license": "MIT",
87 "scripts": {
88 "test": "export NODE_ENV=test && mocha",
89 "build": "waffle",
90 "lint": "eslint '{src,test}/**/*.ts'",
91 "lint:fix": "eslint --fix '{src,test}/**/*.ts'"
92 },
93 "devDependencies": {
94 "@openzeppelin/contracts": "^4.3.1",
95 "@types/chai": "^4.2.3",
96 "@types/mocha": "^5.2.7",
97 "@typescript-eslint/eslint-plugin": "^2.30.0",
98 "@typescript-eslint/parser": "^2.30.0",
99 "chai": "^4.3.4",
100 "eslint": "^6.8.0",
101 "eslint-plugin-import": "^2.20.2",
102 "ethereum-waffle": "^3.4.0",
103 "ethers": "^5.0.17",
104 "mocha": "^7.2.0",
105 "ts-node": "^8.9.1",
106 "typescript": "^3.8.3"
107 }
108}
109{
110 "compilerOptions": {
111 "declaration": true,
112 "esModuleInterop": true,
113 "lib": [
114 "ES2018"
115 ],
116 "module": "CommonJS",
117 "moduleResolution": "node",
118 "outDir": "dist",
119 "resolveJsonModule": true,
120 "skipLibCheck": true,
121 "strict": true,
122 "target": "ES2018"
123 }
124
125 // custom test in vrfContract
126 it('Tests if a random number is returned', async () => {
127 expect(await vrfContract.getRandomNumber()).to.be.equal(7);
128 });
129}
130
waffle.json
1src____AmIRichAlready.sol
2 |____RandomNumberConsumer.sol
3 |
4test____AmIRichAlready.test.ts
5 |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13 function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17 IERC20 private tokenContract;
18 uint public richness = 1000000 * 10 ** 18;
19
20 constructor (IERC20 _tokenContract) public {
21 tokenContract = _tokenContract;
22 }
23
24 function check() public view returns (bool) {
25 uint balance = tokenContract.balanceOf(msg.sender);
26 return balance > richness;
27 }
28
29 // IS THIS NEEDED???
30 function setRichness(uint256 _richness) public {
31 richness = _richness;
32 }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44 let mockERC20: Contract;
45 let contract: Contract;
46 let vrfContract: Contract;
47 let wallet: Wallet;
48
49 beforeEach(async () => {
50 [wallet] = new MockProvider().getWallets();
51 mockERC20 = await deployMockContract(wallet, IERC20.abi);
52 contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53 vrfContract = await deployContract(wallet, RandomNumberConsumer);
54 });
55
56 it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57 await mockERC20.mock.balanceOf
58 .withArgs(wallet.address)
59 .returns(utils.parseEther('999999'));
60 await contract.check();
61 expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62 });
63
64 it('returns false if the wallet has less than 1000000 coins', async () => {
65 await mockERC20.mock.balanceOf
66 .withArgs(wallet.address)
67 .returns(utils.parseEther('999999'));
68 expect(await contract.check()).to.be.equal(false);
69 });
70
71 it('returns true if the wallet has at least 1000000 coins', async () => {
72 await mockERC20.mock.balanceOf
73 .withArgs(wallet.address)
74 .returns(utils.parseEther('1000000'));
75 expect(await contract.check()).to.be.equal(false);
76 });
77});
78-r ts-node/register/transpile-only
79--timeout 50000
80--no-warnings
81test/**/*.test.{js,ts}
82{
83 "name": "example-dynamic-mocking-and-testing-calls",
84 "version": "1.0.0",
85 "main": "index.js",
86 "license": "MIT",
87 "scripts": {
88 "test": "export NODE_ENV=test && mocha",
89 "build": "waffle",
90 "lint": "eslint '{src,test}/**/*.ts'",
91 "lint:fix": "eslint --fix '{src,test}/**/*.ts'"
92 },
93 "devDependencies": {
94 "@openzeppelin/contracts": "^4.3.1",
95 "@types/chai": "^4.2.3",
96 "@types/mocha": "^5.2.7",
97 "@typescript-eslint/eslint-plugin": "^2.30.0",
98 "@typescript-eslint/parser": "^2.30.0",
99 "chai": "^4.3.4",
100 "eslint": "^6.8.0",
101 "eslint-plugin-import": "^2.20.2",
102 "ethereum-waffle": "^3.4.0",
103 "ethers": "^5.0.17",
104 "mocha": "^7.2.0",
105 "ts-node": "^8.9.1",
106 "typescript": "^3.8.3"
107 }
108}
109{
110 "compilerOptions": {
111 "declaration": true,
112 "esModuleInterop": true,
113 "lib": [
114 "ES2018"
115 ],
116 "module": "CommonJS",
117 "moduleResolution": "node",
118 "outDir": "dist",
119 "resolveJsonModule": true,
120 "skipLibCheck": true,
121 "strict": true,
122 "target": "ES2018"
123 }
124
125 // custom test in vrfContract
126 it('Tests if a random number is returned', async () => {
127 expect(await vrfContract.getRandomNumber()).to.be.equal(7);
128 });
129}
130{
131 "compilerType": "solcjs",
132 "compilerVersion": "0.6.2",
133 "sourceDirectory": "./src",
134 "outputDirectory": "./build"
135}
136
The yarn.lock
file content is a bit large, and it's auto-generated, so you can find it on the Waffle framework repository. Similarly, the package.json
can be found here, in the same repository.
One can also simply clone the repo with the specified filestructure here, and run the tests with the following commands:
1src____AmIRichAlready.sol
2 |____RandomNumberConsumer.sol
3 |
4test____AmIRichAlready.test.ts
5 |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13 function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17 IERC20 private tokenContract;
18 uint public richness = 1000000 * 10 ** 18;
19
20 constructor (IERC20 _tokenContract) public {
21 tokenContract = _tokenContract;
22 }
23
24 function check() public view returns (bool) {
25 uint balance = tokenContract.balanceOf(msg.sender);
26 return balance > richness;
27 }
28
29 // IS THIS NEEDED???
30 function setRichness(uint256 _richness) public {
31 richness = _richness;
32 }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44 let mockERC20: Contract;
45 let contract: Contract;
46 let vrfContract: Contract;
47 let wallet: Wallet;
48
49 beforeEach(async () => {
50 [wallet] = new MockProvider().getWallets();
51 mockERC20 = await deployMockContract(wallet, IERC20.abi);
52 contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53 vrfContract = await deployContract(wallet, RandomNumberConsumer);
54 });
55
56 it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57 await mockERC20.mock.balanceOf
58 .withArgs(wallet.address)
59 .returns(utils.parseEther('999999'));
60 await contract.check();
61 expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62 });
63
64 it('returns false if the wallet has less than 1000000 coins', async () => {
65 await mockERC20.mock.balanceOf
66 .withArgs(wallet.address)
67 .returns(utils.parseEther('999999'));
68 expect(await contract.check()).to.be.equal(false);
69 });
70
71 it('returns true if the wallet has at least 1000000 coins', async () => {
72 await mockERC20.mock.balanceOf
73 .withArgs(wallet.address)
74 .returns(utils.parseEther('1000000'));
75 expect(await contract.check()).to.be.equal(false);
76 });
77});
78-r ts-node/register/transpile-only
79--timeout 50000
80--no-warnings
81test/**/*.test.{js,ts}
82{
83 "name": "example-dynamic-mocking-and-testing-calls",
84 "version": "1.0.0",
85 "main": "index.js",
86 "license": "MIT",
87 "scripts": {
88 "test": "export NODE_ENV=test && mocha",
89 "build": "waffle",
90 "lint": "eslint '{src,test}/**/*.ts'",
91 "lint:fix": "eslint --fix '{src,test}/**/*.ts'"
92 },
93 "devDependencies": {
94 "@openzeppelin/contracts": "^4.3.1",
95 "@types/chai": "^4.2.3",
96 "@types/mocha": "^5.2.7",
97 "@typescript-eslint/eslint-plugin": "^2.30.0",
98 "@typescript-eslint/parser": "^2.30.0",
99 "chai": "^4.3.4",
100 "eslint": "^6.8.0",
101 "eslint-plugin-import": "^2.20.2",
102 "ethereum-waffle": "^3.4.0",
103 "ethers": "^5.0.17",
104 "mocha": "^7.2.0",
105 "ts-node": "^8.9.1",
106 "typescript": "^3.8.3"
107 }
108}
109{
110 "compilerOptions": {
111 "declaration": true,
112 "esModuleInterop": true,
113 "lib": [
114 "ES2018"
115 ],
116 "module": "CommonJS",
117 "moduleResolution": "node",
118 "outDir": "dist",
119 "resolveJsonModule": true,
120 "skipLibCheck": true,
121 "strict": true,
122 "target": "ES2018"
123 }
124
125 // custom test in vrfContract
126 it('Tests if a random number is returned', async () => {
127 expect(await vrfContract.getRandomNumber()).to.be.equal(7);
128 });
129}
130{
131 "compilerType": "solcjs",
132 "compilerVersion": "0.6.2",
133 "sourceDirectory": "./src",
134 "outputDirectory": "./build"
135}
136git clone git@github.com:a-t-2/chainlink.git
137git clone git@github.com:a-t-2/test_vrf3.git
138cd test_vrf3
139sudo apt install npm
140npm install
141npm audit fix
142npm install --save-dev ethereum-waffle
143npm install @openzeppelin/contracts -D
144npm i chai -D
145npm i mocha -D
146rm -r build
147npx waffle
148npx mocha
149npm test
150
This will test the AmIRichAlready.sol
file and output:
1src____AmIRichAlready.sol
2 |____RandomNumberConsumer.sol
3 |
4test____AmIRichAlready.test.ts
5 |____mocha.opts
6package.json
7tsconfig.json
8waffle.json
9yarn.lock
10pragma solidity ^0.6.2;
11
12interface IERC20 {
13 function balanceOf(address account) external view returns (uint256);
14}
15
16contract AmIRichAlready {
17 IERC20 private tokenContract;
18 uint public richness = 1000000 * 10 ** 18;
19
20 constructor (IERC20 _tokenContract) public {
21 tokenContract = _tokenContract;
22 }
23
24 function check() public view returns (bool) {
25 uint balance = tokenContract.balanceOf(msg.sender);
26 return balance > richness;
27 }
28
29 // IS THIS NEEDED???
30 function setRichness(uint256 _richness) public {
31 richness = _richness;
32 }
33}
34import {expect, use} from 'chai';
35import {Contract, utils, Wallet} from 'ethers';
36import {deployContract, deployMockContract, MockProvider, solidity} from 'ethereum-waffle';
37
38import IERC20 from '../build/IERC20.json';
39import AmIRichAlready from '../build/AmIRichAlready.json';
40
41use(solidity);
42
43describe('Am I Rich Already', () => {
44 let mockERC20: Contract;
45 let contract: Contract;
46 let vrfContract: Contract;
47 let wallet: Wallet;
48
49 beforeEach(async () => {
50 [wallet] = new MockProvider().getWallets();
51 mockERC20 = await deployMockContract(wallet, IERC20.abi);
52 contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]);
53 vrfContract = await deployContract(wallet, RandomNumberConsumer);
54 });
55
56 it('checks if contract called balanceOf with certain wallet on the ERC20 token', async () => {
57 await mockERC20.mock.balanceOf
58 .withArgs(wallet.address)
59 .returns(utils.parseEther('999999'));
60 await contract.check();
61 expect('balanceOf').to.be.calledOnContractWith(mockERC20, [wallet.address]);
62 });
63
64 it('returns false if the wallet has less than 1000000 coins', async () => {
65 await mockERC20.mock.balanceOf
66 .withArgs(wallet.address)
67 .returns(utils.parseEther('999999'));
68 expect(await contract.check()).to.be.equal(false);
69 });
70
71 it('returns true if the wallet has at least 1000000 coins', async () => {
72 await mockERC20.mock.balanceOf
73 .withArgs(wallet.address)
74 .returns(utils.parseEther('1000000'));
75 expect(await contract.check()).to.be.equal(false);
76 });
77});
78-r ts-node/register/transpile-only
79--timeout 50000
80--no-warnings
81test/**/*.test.{js,ts}
82{
83 "name": "example-dynamic-mocking-and-testing-calls",
84 "version": "1.0.0",
85 "main": "index.js",
86 "license": "MIT",
87 "scripts": {
88 "test": "export NODE_ENV=test && mocha",
89 "build": "waffle",
90 "lint": "eslint '{src,test}/**/*.ts'",
91 "lint:fix": "eslint --fix '{src,test}/**/*.ts'"
92 },
93 "devDependencies": {
94 "@openzeppelin/contracts": "^4.3.1",
95 "@types/chai": "^4.2.3",
96 "@types/mocha": "^5.2.7",
97 "@typescript-eslint/eslint-plugin": "^2.30.0",
98 "@typescript-eslint/parser": "^2.30.0",
99 "chai": "^4.3.4",
100 "eslint": "^6.8.0",
101 "eslint-plugin-import": "^2.20.2",
102 "ethereum-waffle": "^3.4.0",
103 "ethers": "^5.0.17",
104 "mocha": "^7.2.0",
105 "ts-node": "^8.9.1",
106 "typescript": "^3.8.3"
107 }
108}
109{
110 "compilerOptions": {
111 "declaration": true,
112 "esModuleInterop": true,
113 "lib": [
114 "ES2018"
115 ],
116 "module": "CommonJS",
117 "moduleResolution": "node",
118 "outDir": "dist",
119 "resolveJsonModule": true,
120 "skipLibCheck": true,
121 "strict": true,
122 "target": "ES2018"
123 }
124
125 // custom test in vrfContract
126 it('Tests if a random number is returned', async () => {
127 expect(await vrfContract.getRandomNumber()).to.be.equal(7);
128 });
129}
130{
131 "compilerType": "solcjs",
132 "compilerVersion": "0.6.2",
133 "sourceDirectory": "./src",
134 "outputDirectory": "./build"
135}
136git clone git@github.com:a-t-2/chainlink.git
137git clone git@github.com:a-t-2/test_vrf3.git
138cd test_vrf3
139sudo apt install npm
140npm install
141npm audit fix
142npm install --save-dev ethereum-waffle
143npm install @openzeppelin/contracts -D
144npm i chai -D
145npm i mocha -D
146rm -r build
147npx waffle
148npx mocha
149npm test
150 Am I Rich Already
151 ✓ checks if contract called balanceOf with certain wallet on the ERC20 token (249ms)
152 ✓ returns false if the wallet has less than 1000000 coins (190ms)
153 ✓ returns true if the wallet has at least 1000000 coins (159ms)
154 Tests if a random number is returned:
155 Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"name":"RuntimeError","results":{"0x0a0b028de6cf6e8446853a300061305501136cefa5f5eb3e96afd95dbd73dd92":{"error":"revert","program_counter":609,"return":"0x"}},"hashes":["0x0a0b028de6cf6e8446853a300061305501136cefa5f5eb3e96afd95dbd73dd92"],"message":"VM Exception while processing transaction: revert"}, tx={"data":"0xdbdff2c1","to":{},"from":"0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff","gasPrice":{"type":"BigNumber","hex":"0x77359400"},"type":0,"nonce":{},"gasLimit":{},"chainId":{}}, code=UNPREDICTABLE_GAS_LIMIT, version=abstract-signer/5.4.1)
156 at Logger.makeError (node_modules/@ethersproject/logger/src.ts/index.ts:225:28)
157 at Logger.throwError (node_modules/@ethersproject/logger/src.ts/index.ts:237:20)
158 at /home/name/git/trucol/tested/new_test/test_vrf3/node_modules/@ethersproject/abstract-signer/src.ts/index.ts:301:31
159 at process._tickCallback (internal/process/next_tick.js:68:7)
160
161
162
163 3 passing (4s)
164
Which set of files, file structure and commands do I need to automatically test whether the getRandomNumber()
contract returns an integer if sufficient "gas" is provided, and an error otherwise?
ANSWER
Answered 2021-Sep-09 at 04:35to test locally you need to make use of mocks which can simulate having an oracle network. Because you're working locally, a Chainlink node doesn't know about your local blockchain, so you can't actually do proper VRF requests. Note you can try deploy a local Chainlink node and a local blockchain and have them talk, but it isn't fully supported yet so you may get mixed results. Anyway, as per the hardhat starter kit that you linked, you can set the defaultNetwork to be 'hardhat' in the hardhat.config.js file, then when you deploy and run the integration tests (yarn test-integration), it will use mocks to mock up the VRF node, and to test the requesting of a random number. See the test here, and the mock contracts and linktoken get deployed here
QUESTION
Trying to run "brownie run .\scripts\deploy.py --network rinkeby" but getting a ValueError
Asked 2022-Mar-01 at 18:15Hey guys I am trying to deploy my project on the rinkeby chain using infura, but I am getting a ValueError Here is my trackback:
1INFO: Could not find files for the given pattern(s).
2Brownie v1.17.1 - Python development framework for Ethereum
3
4 File "c:\users\allow\appdata\local\programs\python\python39\lib\site-packages\brownie\_cli\__main__.py", line 64, in main
5 importlib.import_module(f"brownie._cli.{cmd}").main()
6 File "c:\users\allow\appdata\local\programs\python\python39\lib\site-packages\brownie\_cli\run.py", line 44, in main
7 network.connect(CONFIG.argv["network"])
8 File "c:\users\allow\appdata\local\programs\python\python39\lib\site-packages\brownie\network\main.py", line 40, in connect
9 web3.connect(host, active.get("timeout", 30))
10 File "c:\users\allow\appdata\local\programs\python\python39\lib\site-packages\brownie\network\web3.py", line 52, in connect
11 uri = _expand_environment_vars(uri)
12 File "c:\users\allow\appdata\local\programs\python\python39\lib\site-packages\brownie\network\web3.py", line 183, in _expand_environment_vars
13 raise ValueError(f"Unable to expand environment variable in host setting: '{uri}'")
14ValueError: Unable to expand environment variable in host setting: 'https://rinkeby.infura.io/v3/$WEB3_INFURA_PROJECT_ID'
15
Here is my deploy.py code
1INFO: Could not find files for the given pattern(s).
2Brownie v1.17.1 - Python development framework for Ethereum
3
4 File "c:\users\allow\appdata\local\programs\python\python39\lib\site-packages\brownie\_cli\__main__.py", line 64, in main
5 importlib.import_module(f"brownie._cli.{cmd}").main()
6 File "c:\users\allow\appdata\local\programs\python\python39\lib\site-packages\brownie\_cli\run.py", line 44, in main
7 network.connect(CONFIG.argv["network"])
8 File "c:\users\allow\appdata\local\programs\python\python39\lib\site-packages\brownie\network\main.py", line 40, in connect
9 web3.connect(host, active.get("timeout", 30))
10 File "c:\users\allow\appdata\local\programs\python\python39\lib\site-packages\brownie\network\web3.py", line 52, in connect
11 uri = _expand_environment_vars(uri)
12 File "c:\users\allow\appdata\local\programs\python\python39\lib\site-packages\brownie\network\web3.py", line 183, in _expand_environment_vars
13 raise ValueError(f"Unable to expand environment variable in host setting: '{uri}'")
14ValueError: Unable to expand environment variable in host setting: 'https://rinkeby.infura.io/v3/$WEB3_INFURA_PROJECT_ID'
15from brownie import accounts, config, SimpleStorage, network
16import os
17
18def deploy_simple_storage():
19 account = get_account()
20 simple_storage = SimpleStorage.deploy({"from": account})
21 stored_value = simple_storage.retrieve()
22 print(stored_value)
23 transaction = simple_storage.store(15, {"from": account})
24 transaction.wait(1)
25 updated_stored_value = simple_storage.retrieve()
26 print(updated_stored_value)
27
28
29def get_account():
30 if network.show_active() == "development":
31 return accounts[0]
32 else:
33 return accounts.add(config["wallets"]["from_key"])
34
35
36def main():
37 deploy_simple_storage()
38
I have a really little experience in coding. I think the problem is related to .env, but I don't know what I should now. FYI I am using windows n follow this course https://www.youtube.com/watch?v=M576WGiDBdQ stuck at 4:48:00
ANSWER
Answered 2021-Nov-28 at 10:14it appears your env variables are not set correctly, and it looks like in this case it's your WEB3_INFURA_PROJECT_ID.
You can fix it by setting the variable in your .env file and adding dotenv: .env to your brownie-config.yaml.
brownie-config.yaml:
dotenv: .env .env:
export WEB3_INFURA_PROJECT_ID=YOUR_PROJECT_ID_HERE Remember to save these files.
Additionally, you should be on at least brownie version v1.14.6. You can find out what version you're on with:
brownie --version
QUESTION
Flutter - How to refresh a Widget on button Click?
Asked 2022-Mar-01 at 10:15I'm making an app where I plot charts of cryptocurrency. I have a file like this, that renders a chart of btc
/24h
in it. I'm using chart_sparkline
package to plot the chart.
I have the following code, and it is not working on a button click, how do I fix this?
1import 'package:flutter/material.dart';
2import 'package:tracker/renderchart.dart';
3
4class Portfolio extends StatefulWidget {
5 @override
6 _PortfolioState createState() => _PortfolioState();
7}
8
9class _PortfolioState extends State<Portfolio> {
10 Widget portfolioChart = RenderPortfolioChart(coin: "bitcoin", days: 1);
11
12 @override
13 Widget build(BuildContext context) {
14 return Container(
15 child: Column(
16 children: [
17 portfolioChart,
18
19 const Padding(padding: EdgeInsets.only(top: 10.0)),
20
21 const Text("Hello, there!", style: TextStyle(color: Colors.white)),
22
23 const Padding(padding: EdgeInsets.only(top: 10.0)),
24
25 ElevatedButton(
26 onPressed: (){
27 print("updating chart");
28 setState(() {
29 portfolioChart = RenderPortfolioChart(coin: "ethereum", days: 1);
30 });
31 },
32
33 child: Text("ETH"),
34 )
35 ]
36 ),
37 );
38 }
39}
40
Basically, the elevatedButton should update the chart, but it is not working in my case, how to fix this?
ANSWER
Answered 2022-Mar-01 at 10:15I fixed this, I was passing constructor parameters of Portfolio
to _PortfolioState
, this won't update the values the next time. Instead of passing these values to _PortfolioState
, I used widget.coin
and widget.days
to extract the data from the Portfolio
class.
Thanks to this StackOverflow link: Passing Data to a Stateful Widget in Flutter
QUESTION
Flag provided but not defined: -rpc
Asked 2022-Feb-19 at 20:07Am starting off in blockchain development using the book Mastering Blockchain - A deep dive into distributed ledgers, consensus protocols, smart contracts, DApps, cryptocurrencies, Ethereum,
Am using WSL with geth version 1.10.9.
1$geth version
2Geth
3Version: 1.10.9-stable
4Git Commit: eae3b1946a276ac099e0018fc792d9e8c3bfda6d
5Architecture: amd64
6Go Version: go1.17
7Operating System: linux
8GOPATH=
9GOROOT=go
10
Am trying to start geth, but am getting the error that the --rpc flag is not defined.
This is the command I am trying to run:
geth --datadir ~/etherprivate/ --networkid 786 --rpc --rpcapi 'web3,eth,net,debug,personal' --rpccorsdomain '*'
Any help on how I can solve it?
ANSWER
Answered 2021-Oct-11 at 23:20It appears 1.10.9-stable version has a problem and is returning a -rpc error. GETH 1.10.8-stable version works fine when running the geth command with --rpc
QUESTION
Brownie testing for reverted transactions does not work with pytest.raises() or brownie.reverts()
Asked 2022-Feb-19 at 19:52Issue description: Brownie tests containing either
1pytest.raises(exceptions.VirtualMachineError)
2
or
1pytest.raises(exceptions.VirtualMachineError)
2brownie.reverts()
3
producing an error, when the request by design fails (is reverted).
On GitHub: https://github.com/n4n0b1t3/brownie.reverts.example
Expected behavior: The test should either fail or succeed, depending on the outcome of the transaction.
Noticeable: When the test is set up in a way, that the transaction is not reverted, the test works correctly without producing an error.
What I have tried so far: I reduced the code to remove all unnecessary dependencies to contain only the problematic parts. After a complete new setup of a python virtual environment with only the necessary features (described below under setup), I ran the code again, to make sure the issue prevails and is not solved.
Source code of projectroot/sourcecode/contracts/ExampleContract.sol
1pytest.raises(exceptions.VirtualMachineError)
2brownie.reverts()
3// SPDX-License-Identifier: MIT
4
5pragma solidity >=0.6.6 <0.9.0;
6
7contract ExampleContract {
8 address public owner;
9
10 constructor() {
11 owner = msg.sender;
12 }
13
14 modifier onlyOwner() {
15 require(msg.sender == owner, "only owner");
16 _;
17 }
18
19 function withdraw() public payable onlyOwner {
20 payable(msg.sender).transfer(address(this).balance);
21 }
22}
23
Exhibit A Source code of projectroot/sourcecode/test/test_reverts.py
1pytest.raises(exceptions.VirtualMachineError)
2brownie.reverts()
3// SPDX-License-Identifier: MIT
4
5pragma solidity >=0.6.6 <0.9.0;
6
7contract ExampleContract {
8 address public owner;
9
10 constructor() {
11 owner = msg.sender;
12 }
13
14 modifier onlyOwner() {
15 require(msg.sender == owner, "only owner");
16 _;
17 }
18
19 function withdraw() public payable onlyOwner {
20 payable(msg.sender).transfer(address(this).balance);
21 }
22}
23import brownie
24from brownie import ExampleContract, accounts, exceptions
25
26
27def test_only_owner_can_withdraw():
28 example_contract = ExampleContract.deploy({"from": accounts[0]})
29 bad_account = accounts.add()
30 with brownie.reverts():
31 example_contract.withdraw({"from": bad_account})
32
Exhibit B Alternative making use of pytest.raises()
1pytest.raises(exceptions.VirtualMachineError)
2brownie.reverts()
3// SPDX-License-Identifier: MIT
4
5pragma solidity >=0.6.6 <0.9.0;
6
7contract ExampleContract {
8 address public owner;
9
10 constructor() {
11 owner = msg.sender;
12 }
13
14 modifier onlyOwner() {
15 require(msg.sender == owner, "only owner");
16 _;
17 }
18
19 function withdraw() public payable onlyOwner {
20 payable(msg.sender).transfer(address(this).balance);
21 }
22}
23import brownie
24from brownie import ExampleContract, accounts, exceptions
25
26
27def test_only_owner_can_withdraw():
28 example_contract = ExampleContract.deploy({"from": accounts[0]})
29 bad_account = accounts.add()
30 with brownie.reverts():
31 example_contract.withdraw({"from": bad_account})
32import brownie
33import pytest
34from brownie import ExampleContract, accounts, exceptions
35
36def test_only_owner_can_withdraw():
37 example_contract = ExampleContract.deploy({"from": accounts[0]})
38 bad_account = accounts.add()
39 with pytest.raises(exceptions.VirtualMachineError):
40 example_contract.withdraw({"from": bad_account})
41
Exhibit C Alternative with not reverting transaction, which is correctly working:
1pytest.raises(exceptions.VirtualMachineError)
2brownie.reverts()
3// SPDX-License-Identifier: MIT
4
5pragma solidity >=0.6.6 <0.9.0;
6
7contract ExampleContract {
8 address public owner;
9
10 constructor() {
11 owner = msg.sender;
12 }
13
14 modifier onlyOwner() {
15 require(msg.sender == owner, "only owner");
16 _;
17 }
18
19 function withdraw() public payable onlyOwner {
20 payable(msg.sender).transfer(address(this).balance);
21 }
22}
23import brownie
24from brownie import ExampleContract, accounts, exceptions
25
26
27def test_only_owner_can_withdraw():
28 example_contract = ExampleContract.deploy({"from": accounts[0]})
29 bad_account = accounts.add()
30 with brownie.reverts():
31 example_contract.withdraw({"from": bad_account})
32import brownie
33import pytest
34from brownie import ExampleContract, accounts, exceptions
35
36def test_only_owner_can_withdraw():
37 example_contract = ExampleContract.deploy({"from": accounts[0]})
38 bad_account = accounts.add()
39 with pytest.raises(exceptions.VirtualMachineError):
40 example_contract.withdraw({"from": bad_account})
41import brownie
42from brownie import ExampleContract, accounts, exceptions
43
44def test_only_owner_can_withdraw():
45 example_contract = ExampleContract.deploy({"from": accounts[0]})
46 bad_account = accounts.add()
47 with brownie.reverts():
48 example_contract.withdraw({"from": accounts[0]})
49
With the result:
1pytest.raises(exceptions.VirtualMachineError)
2brownie.reverts()
3// SPDX-License-Identifier: MIT
4
5pragma solidity >=0.6.6 <0.9.0;
6
7contract ExampleContract {
8 address public owner;
9
10 constructor() {
11 owner = msg.sender;
12 }
13
14 modifier onlyOwner() {
15 require(msg.sender == owner, "only owner");
16 _;
17 }
18
19 function withdraw() public payable onlyOwner {
20 payable(msg.sender).transfer(address(this).balance);
21 }
22}
23import brownie
24from brownie import ExampleContract, accounts, exceptions
25
26
27def test_only_owner_can_withdraw():
28 example_contract = ExampleContract.deploy({"from": accounts[0]})
29 bad_account = accounts.add()
30 with brownie.reverts():
31 example_contract.withdraw({"from": bad_account})
32import brownie
33import pytest
34from brownie import ExampleContract, accounts, exceptions
35
36def test_only_owner_can_withdraw():
37 example_contract = ExampleContract.deploy({"from": accounts[0]})
38 bad_account = accounts.add()
39 with pytest.raises(exceptions.VirtualMachineError):
40 example_contract.withdraw({"from": bad_account})
41import brownie
42from brownie import ExampleContract, accounts, exceptions
43
44def test_only_owner_can_withdraw():
45 example_contract = ExampleContract.deploy({"from": accounts[0]})
46 bad_account = accounts.add()
47 with brownie.reverts():
48 example_contract.withdraw({"from": accounts[0]})
49>raise AssertionError("Transaction did not revert")
50E AssertionError: Transaction did not revert
51
Complete terminal output for exhibits A and B
1pytest.raises(exceptions.VirtualMachineError)
2brownie.reverts()
3// SPDX-License-Identifier: MIT
4
5pragma solidity >=0.6.6 <0.9.0;
6
7contract ExampleContract {
8 address public owner;
9
10 constructor() {
11 owner = msg.sender;
12 }
13
14 modifier onlyOwner() {
15 require(msg.sender == owner, "only owner");
16 _;
17 }
18
19 function withdraw() public payable onlyOwner {
20 payable(msg.sender).transfer(address(this).balance);
21 }
22}
23import brownie
24from brownie import ExampleContract, accounts, exceptions
25
26
27def test_only_owner_can_withdraw():
28 example_contract = ExampleContract.deploy({"from": accounts[0]})
29 bad_account = accounts.add()
30 with brownie.reverts():
31 example_contract.withdraw({"from": bad_account})
32import brownie
33import pytest
34from brownie import ExampleContract, accounts, exceptions
35
36def test_only_owner_can_withdraw():
37 example_contract = ExampleContract.deploy({"from": accounts[0]})
38 bad_account = accounts.add()
39 with pytest.raises(exceptions.VirtualMachineError):
40 example_contract.withdraw({"from": bad_account})
41import brownie
42from brownie import ExampleContract, accounts, exceptions
43
44def test_only_owner_can_withdraw():
45 example_contract = ExampleContract.deploy({"from": accounts[0]})
46 bad_account = accounts.add()
47 with brownie.reverts():
48 example_contract.withdraw({"from": accounts[0]})
49>raise AssertionError("Transaction did not revert")
50E AssertionError: Transaction did not revert
51(.venv) testcode>brownie test
52INFORMATION: Es konnten keine Dateien mit dem angegebenen
53Muster gefunden werden.
54Brownie v1.16.4 - Python development framework for Ethereum
55
56======================================================================================================= test session starts =======================================================================================================
57platform win32 -- Python 3.10.2, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
58rootdir: C:\Users\Zarathustra\blockchainProjects\testing.revert\testcode
59plugins: eth-brownie-1.16.4, hypothesis-6.21.6, forked-1.3.0, xdist-1.34.0, web3-5.23.1
60collected 1 item
61
62Launching 'ganache-cli.cmd --accounts 10 --hardfork istanbul --gasLimit 12000000 --mnemonic brownie --port 8545'...
63
64tests\test_reverts.py F [100%]
65
66============================================================================================================ FAILURES =============================================================================================================
67__________________________________________________________________________________________________ test_only_owner_can_withdraw ___________________________________________________________________________________________________
68
69 def test_only_owner_can_withdraw():
70 fund_me = ExampleContract.deploy({"from": accounts[0]})
71 print(f"FundMe deployed to {fund_me.address}")
72 good = accounts[0]
73 bad = accounts.add()
74 # with pytest.raises(exceptions.VirtualMachineError):
75> with brownie.reverts():
76
77tests\test_reverts.py:12:
78_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
79tests\test_reverts.py:13: in test_only_owner_can_withdraw
80 fund_me.withdraw({"from": bad})
81..\.venv\lib\site-packages\brownie\network\contract.py:1693: in __call__
82 return self.transact(*args)
83..\.venv\lib\site-packages\brownie\network\contract.py:1566: in transact
84 return tx["from"].transfer(
85..\.venv\lib\site-packages\brownie\network\account.py:680: in transfer
86 receipt._raise_if_reverted(exc)
87_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
88
89self = <Transaction '0x1f310675db8ad41f0eb4cd9338f35f2800174168b18c019645b5b1d82ade2826'>, exc = None
90
91 def _raise_if_reverted(self, exc: Any) -> None:
92 if self.status or CONFIG.mode == "console":
93 return
94 if not web3.supports_traces:
95 # if traces are not available, do not attempt to determine the revert reason
96 raise exc or ValueError("Execution reverted")
97
98 if self._dev_revert_msg is None:
99 # no revert message and unable to check dev string - have to get trace
100 self._expand_trace()
101 if self.contract_address:
102 source = ""
103 elif CONFIG.argv["revert"]:
104 source = self._traceback_string()
105 else:
106 source = self._error_string(1)
107 contract = state._find_contract(self.receiver)
108 if contract:
109 marker = "//" if contract._build["language"] == "Solidity" else "#"
110 line = self._traceback_string().split("\n")[-1]
111 if marker + " dev: " in line:
112 self._dev_revert_msg = line[line.index(marker) + len(marker) : -5].strip()
113
114> raise exc._with_attr(
115 source=source, revert_msg=self._revert_msg, dev_revert_msg=self._dev_revert_msg
116 )
117E AttributeError: 'NoneType' object has no attribute '_with_attr'
118
119..\.venv\lib\site-packages\brownie\network\transaction.py:420: AttributeError
120------------------------------------------------------------------------------------------------------ Captured stdout call -------------------------------------------------------------------------------------------------------
121FundMe deployed to 0x3194cBDC3dbcd3E11a07892e7bA5c3394048Cc87
122mnemonic: 'abandon wisdom slot exclude buyer raccoon desert grid inmate flag state castle'
123===================================================================================================== short test summary info =====================================================================================================
124FAILED tests/test_reverts.py::test_only_owner_can_withdraw - AttributeError: 'NoneType' object has no attribute '_with_attr'
125======================================================================================================== 1 failed in 6.40s ========================================================================================================
126Terminating local RPC client...
127(.venv) testcode>
128
My setting: The root directory contains the .venv virtual python environment. Under venv Cython and Brownie are installed. In VSC I am using the latest solidity compiler. In order to install ganache I opened a powershell with admin rights and activated the virtual environment, installed nodeenv, and connected it with venv. After this step I installed ganache and tested it. Everything is working correctly. Complete projects are tested and work correctly in this setup, besides tests with brownie.reverts().
Here in short the command line overview:
1pytest.raises(exceptions.VirtualMachineError)
2brownie.reverts()
3// SPDX-License-Identifier: MIT
4
5pragma solidity >=0.6.6 <0.9.0;
6
7contract ExampleContract {
8 address public owner;
9
10 constructor() {
11 owner = msg.sender;
12 }
13
14 modifier onlyOwner() {
15 require(msg.sender == owner, "only owner");
16 _;
17 }
18
19 function withdraw() public payable onlyOwner {
20 payable(msg.sender).transfer(address(this).balance);
21 }
22}
23import brownie
24from brownie import ExampleContract, accounts, exceptions
25
26
27def test_only_owner_can_withdraw():
28 example_contract = ExampleContract.deploy({"from": accounts[0]})
29 bad_account = accounts.add()
30 with brownie.reverts():
31 example_contract.withdraw({"from": bad_account})
32import brownie
33import pytest
34from brownie import ExampleContract, accounts, exceptions
35
36def test_only_owner_can_withdraw():
37 example_contract = ExampleContract.deploy({"from": accounts[0]})
38 bad_account = accounts.add()
39 with pytest.raises(exceptions.VirtualMachineError):
40 example_contract.withdraw({"from": bad_account})
41import brownie
42from brownie import ExampleContract, accounts, exceptions
43
44def test_only_owner_can_withdraw():
45 example_contract = ExampleContract.deploy({"from": accounts[0]})
46 bad_account = accounts.add()
47 with brownie.reverts():
48 example_contract.withdraw({"from": accounts[0]})
49>raise AssertionError("Transaction did not revert")
50E AssertionError: Transaction did not revert
51(.venv) testcode>brownie test
52INFORMATION: Es konnten keine Dateien mit dem angegebenen
53Muster gefunden werden.
54Brownie v1.16.4 - Python development framework for Ethereum
55
56======================================================================================================= test session starts =======================================================================================================
57platform win32 -- Python 3.10.2, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
58rootdir: C:\Users\Zarathustra\blockchainProjects\testing.revert\testcode
59plugins: eth-brownie-1.16.4, hypothesis-6.21.6, forked-1.3.0, xdist-1.34.0, web3-5.23.1
60collected 1 item
61
62Launching 'ganache-cli.cmd --accounts 10 --hardfork istanbul --gasLimit 12000000 --mnemonic brownie --port 8545'...
63
64tests\test_reverts.py F [100%]
65
66============================================================================================================ FAILURES =============================================================================================================
67__________________________________________________________________________________________________ test_only_owner_can_withdraw ___________________________________________________________________________________________________
68
69 def test_only_owner_can_withdraw():
70 fund_me = ExampleContract.deploy({"from": accounts[0]})
71 print(f"FundMe deployed to {fund_me.address}")
72 good = accounts[0]
73 bad = accounts.add()
74 # with pytest.raises(exceptions.VirtualMachineError):
75> with brownie.reverts():
76
77tests\test_reverts.py:12:
78_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
79tests\test_reverts.py:13: in test_only_owner_can_withdraw
80 fund_me.withdraw({"from": bad})
81..\.venv\lib\site-packages\brownie\network\contract.py:1693: in __call__
82 return self.transact(*args)
83..\.venv\lib\site-packages\brownie\network\contract.py:1566: in transact
84 return tx["from"].transfer(
85..\.venv\lib\site-packages\brownie\network\account.py:680: in transfer
86 receipt._raise_if_reverted(exc)
87_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
88
89self = <Transaction '0x1f310675db8ad41f0eb4cd9338f35f2800174168b18c019645b5b1d82ade2826'>, exc = None
90
91 def _raise_if_reverted(self, exc: Any) -> None:
92 if self.status or CONFIG.mode == "console":
93 return
94 if not web3.supports_traces:
95 # if traces are not available, do not attempt to determine the revert reason
96 raise exc or ValueError("Execution reverted")
97
98 if self._dev_revert_msg is None:
99 # no revert message and unable to check dev string - have to get trace
100 self._expand_trace()
101 if self.contract_address:
102 source = ""
103 elif CONFIG.argv["revert"]:
104 source = self._traceback_string()
105 else:
106 source = self._error_string(1)
107 contract = state._find_contract(self.receiver)
108 if contract:
109 marker = "//" if contract._build["language"] == "Solidity" else "#"
110 line = self._traceback_string().split("\n")[-1]
111 if marker + " dev: " in line:
112 self._dev_revert_msg = line[line.index(marker) + len(marker) : -5].strip()
113
114> raise exc._with_attr(
115 source=source, revert_msg=self._revert_msg, dev_revert_msg=self._dev_revert_msg
116 )
117E AttributeError: 'NoneType' object has no attribute '_with_attr'
118
119..\.venv\lib\site-packages\brownie\network\transaction.py:420: AttributeError
120------------------------------------------------------------------------------------------------------ Captured stdout call -------------------------------------------------------------------------------------------------------
121FundMe deployed to 0x3194cBDC3dbcd3E11a07892e7bA5c3394048Cc87
122mnemonic: 'abandon wisdom slot exclude buyer raccoon desert grid inmate flag state castle'
123===================================================================================================== short test summary info =====================================================================================================
124FAILED tests/test_reverts.py::test_only_owner_can_withdraw - AttributeError: 'NoneType' object has no attribute '_with_attr'
125======================================================================================================== 1 failed in 6.40s ========================================================================================================
126Terminating local RPC client...
127(.venv) testcode>
128projectroot>.\.venv\Scripts\Activate.ps1
129(.venv) projectroot>pip install nodeenv
130(.venv) projectroot>nodeenv -p
131(.venv) projectroot>npm install -g ganache
132(.venv) projectroot>ganache --version
133(.venv) projectroot>mkdir sourcecode
134(.venv) projectroot>cd sourcecode
135(.venv) sourcecode>brownie init
136(.venv) sourcecode>brownie --version
137
ANSWER
Answered 2022-Feb-19 at 19:52This is fixed in Brownie v1.18.1. However, you will need to install Python 3.9.10 in order to get the latest brownie. For this to work in a virtual environment you can't use venv. Here is a process that works for me:
- install virtualenv on your standard Python version
- download python 3.9.10 and install it without "add to path" into a dedicated directory e.g. $home/pythonversions
- in your project directory create a virtual environment like so
python -m virtualenv -p="<path to the python executable >" <virtual_environment_directory>
start your virtual environment e.g. home>..venv\Scripts\activate.ps1
test if your python version is the desired one with python --version
Now install Cython to avoid another error.
Install nodeenv in order to install ganage
Activate with
nodeenv -p
(for this step you will need PowerShell with admin rights)Install ganache with npm
Install eth-brownie with pip check if you got the latest version with
brownie --version
QUESTION
Solidity version to learn
Asked 2022-Feb-08 at 14:21I am new to Ethereum & solidity, I have contributed to a couple of solidity tutorials. I am confused about the different solidity versions in each course, 0.4 and 0.5, whereas the current version is 0.8. The question is should I search to find the course that works with the latest solidity version 0.8? And is Solidity 0.4 or 0.5 outdated? I can see something about the solidity version modifier, is that practical? Please help. Thanks
ANSWER
Answered 2022-Jan-31 at 10:04There is no simple answer to this question, but I will give it a try.
It would be of course best if you can find a course that is using the version 0.8 of Solidity. That way, you can learn all the latest Solidity features that were introduced in the past couple of years. However, fact that the course us using version 0.8 should not be the only criteria. For example, it is also important that the course has good approach in teaching you the concepts of smart contracts and how is that realized on the Ethereum platform. I personally have learned Ethereum platform and Solidity using a course which uses outdated Solidity version. But the course itself was good, and has given me a good foundation. It was easy for me to then pick up the differences that were introduced in the later versions. However, note that I am an software engineer with over 10 years of experience, so that helps a lot.
With all that said, my suggestion would be the following. If you are an experienced developer, just go with any course that has good reviews, you can figure out the differences between the version without much issues. If you are however new to the world of software development, try finding a course that uses some more recent version, as you might struggle with some of the differences.
QUESTION
ParserError: Source file requires different compiler version
Asked 2022-Feb-08 at 13:18I tried all that you mentioned in the discussion here (in other questions) and at https://github.com/smartcontractkit/full-blockchain-solidity-course-py/discussions/522 , however it is not solving the issue for me, I also noticed that the current compiler version remains (current compiler is 0.6.12+commit.27d51765.Windows.msvc). But when I right click and select Solidty:Compiler information, it shows 0.8.0.
from output:
1Retrieving compiler information:
2Compiler using remote version: 'v0.8.0+commit.c7dfd78e', solidity version: 0.8.0+commit.c7dfd78e.Emscripten.clang
3
Not sure if that is related to the issue I face. Anyways starting with the problem I see when running brownie compile. I get the error below:
error in terminal:
1Retrieving compiler information:
2Compiler using remote version: 'v0.8.0+commit.c7dfd78e', solidity version: 0.8.0+commit.c7dfd78e.Emscripten.clang
3PS D:\Python projects\Solidity dev\demo\smartcontract-lottery> brownie compile
4INFO: Could not find files for the given pattern(s).
5Brownie v1.17.2 - Python development framework for Ethereum
6
7Compiling contracts...
8 Solc version: 0.6.12
9 Optimizer: Enabled Runs: 200
10 EVM Version: Istanbul
11CompilerError: solc returned the following errors:
12
13C:/Users/rosne/.brownie/packages/OpenZeppelin/openzeppelin-contracts@4.3.0/contracts/access/Ownable.sol:3:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
14pragma solidity ^0.8.0;
15^---------------------^
16
17C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.8/VRFConsumerBase.sol:2:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
18pragma solidity ^0.8.0;
19^---------------------^
20
21PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
22
My .sol file is Lottery.sol:
1Retrieving compiler information:
2Compiler using remote version: 'v0.8.0+commit.c7dfd78e', solidity version: 0.8.0+commit.c7dfd78e.Emscripten.clang
3PS D:\Python projects\Solidity dev\demo\smartcontract-lottery> brownie compile
4INFO: Could not find files for the given pattern(s).
5Brownie v1.17.2 - Python development framework for Ethereum
6
7Compiling contracts...
8 Solc version: 0.6.12
9 Optimizer: Enabled Runs: 200
10 EVM Version: Istanbul
11CompilerError: solc returned the following errors:
12
13C:/Users/rosne/.brownie/packages/OpenZeppelin/openzeppelin-contracts@4.3.0/contracts/access/Ownable.sol:3:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
14pragma solidity ^0.8.0;
15^---------------------^
16
17C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.8/VRFConsumerBase.sol:2:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
18pragma solidity ^0.8.0;
19^---------------------^
20
21PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
22// SPDX-License-Identifier: MIT
23pragma solidity ^0.6.0;
24
25import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
26import "@openzeppelin/contracts/access/Ownable.sol";
27import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
28
29contract Lottery is VRFConsumerBase, Ownable {
30 uint256 usdEntryFee;
31 address payable[] public players;
32 address payable public recentWinner;
33 uint256 public randomness;
34 AggregatorV3Interface internal ethUsdPriceFeed;
35 enum LOTTERY_STATE {
36 OPEN,
37 CLOSED,
38 CALCULATING_WINNER
39 }
40
41 LOTTERY_STATE public lottery_state;
42 uint256 public fee;
43 bytes32 public keyhash;
44
45 constructor(
46 address _priceFeedAddress,
47 address _vrfCoordinator,
48 address _link,
49 uint256 _fee,
50 bytes32 _keyhash
51 ) public VRFConsumerBase(_vrfCoordinator, _link) {
52 usdEntryFee = 50 * (10**18);
53 ethUsdPriceFeed = AggregatorV3Interface(_priceFeedAddress);
54 lottery_state = LOTTERY_STATE.CLOSED;
55 fee = _fee;
56 keyhash = _keyhash;
57 }
58
59 function enter() public payable {
60 //$50 min
61 require(lottery_state == LOTTERY_STATE.OPEN);
62 require(msg.value >= getEntranceFee(), "Not enough ETH!");
63 players.push(payable(msg.sender));
64 }
65
66 function getEntranceFee() public view returns (uint256) {
67 (, int256 price, , , ) = ethUsdPriceFeed.latestRoundData();
68 uint256 adjustedPrice = uint256(price) * 10**12; //18 decimals
69 //$50, 2000 ETH
70 //50/2000
71 //50*10000/2000
72 uint256 costToEnter = (usdEntryFee * 10**18) / adjustedPrice;
73 return costToEnter;
74 }
75
76 function startLottery() public onlyOwner {
77 require(
78 lottery_state == LOTTERY_STATE.CLOSED,
79 "cant start a new lottery yet"
80 );
81 lottery_state = LOTTERY_STATE.OPEN;
82 }
83
84 function endLottery() public onlyOwner {
85 lottery_state = LOTTERY_STATE.CALCULATING_WINNER;
86 bytes32 requestId = requestRandomness(keyhash, fee);
87 }
88
89 function FulfillRandomness(bytes32 _requestId, uint256 _randomness)
90 internal
91 override
92 {
93 require(
94 lottery_state == LOTTERY_STATE.CALCULATING_WINNER,
95 "you arent there yet!"
96 );
97
98 require(_randomness > 0, "random not found");
99 uint256 indexOfWinner = _randomness % players.length;
100 recentWinner = players[indexOfWinner];
101 recentWinner.transfer(address(this).balance);
102
103 //reset
104
105 players = new address payable[](0);
106 lottery_state = LOTTERY_STATE.CLOSED;
107 randomness = _randomness;
108 }
109}
110
111
I also tried to google some solutions so my settings.json file is a bit different but that didnt help too.
settings.json:
1Retrieving compiler information:
2Compiler using remote version: 'v0.8.0+commit.c7dfd78e', solidity version: 0.8.0+commit.c7dfd78e.Emscripten.clang
3PS D:\Python projects\Solidity dev\demo\smartcontract-lottery> brownie compile
4INFO: Could not find files for the given pattern(s).
5Brownie v1.17.2 - Python development framework for Ethereum
6
7Compiling contracts...
8 Solc version: 0.6.12
9 Optimizer: Enabled Runs: 200
10 EVM Version: Istanbul
11CompilerError: solc returned the following errors:
12
13C:/Users/rosne/.brownie/packages/OpenZeppelin/openzeppelin-contracts@4.3.0/contracts/access/Ownable.sol:3:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
14pragma solidity ^0.8.0;
15^---------------------^
16
17C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.8/VRFConsumerBase.sol:2:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
18pragma solidity ^0.8.0;
19^---------------------^
20
21PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
22// SPDX-License-Identifier: MIT
23pragma solidity ^0.6.0;
24
25import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
26import "@openzeppelin/contracts/access/Ownable.sol";
27import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
28
29contract Lottery is VRFConsumerBase, Ownable {
30 uint256 usdEntryFee;
31 address payable[] public players;
32 address payable public recentWinner;
33 uint256 public randomness;
34 AggregatorV3Interface internal ethUsdPriceFeed;
35 enum LOTTERY_STATE {
36 OPEN,
37 CLOSED,
38 CALCULATING_WINNER
39 }
40
41 LOTTERY_STATE public lottery_state;
42 uint256 public fee;
43 bytes32 public keyhash;
44
45 constructor(
46 address _priceFeedAddress,
47 address _vrfCoordinator,
48 address _link,
49 uint256 _fee,
50 bytes32 _keyhash
51 ) public VRFConsumerBase(_vrfCoordinator, _link) {
52 usdEntryFee = 50 * (10**18);
53 ethUsdPriceFeed = AggregatorV3Interface(_priceFeedAddress);
54 lottery_state = LOTTERY_STATE.CLOSED;
55 fee = _fee;
56 keyhash = _keyhash;
57 }
58
59 function enter() public payable {
60 //$50 min
61 require(lottery_state == LOTTERY_STATE.OPEN);
62 require(msg.value >= getEntranceFee(), "Not enough ETH!");
63 players.push(payable(msg.sender));
64 }
65
66 function getEntranceFee() public view returns (uint256) {
67 (, int256 price, , , ) = ethUsdPriceFeed.latestRoundData();
68 uint256 adjustedPrice = uint256(price) * 10**12; //18 decimals
69 //$50, 2000 ETH
70 //50/2000
71 //50*10000/2000
72 uint256 costToEnter = (usdEntryFee * 10**18) / adjustedPrice;
73 return costToEnter;
74 }
75
76 function startLottery() public onlyOwner {
77 require(
78 lottery_state == LOTTERY_STATE.CLOSED,
79 "cant start a new lottery yet"
80 );
81 lottery_state = LOTTERY_STATE.OPEN;
82 }
83
84 function endLottery() public onlyOwner {
85 lottery_state = LOTTERY_STATE.CALCULATING_WINNER;
86 bytes32 requestId = requestRandomness(keyhash, fee);
87 }
88
89 function FulfillRandomness(bytes32 _requestId, uint256 _randomness)
90 internal
91 override
92 {
93 require(
94 lottery_state == LOTTERY_STATE.CALCULATING_WINNER,
95 "you arent there yet!"
96 );
97
98 require(_randomness > 0, "random not found");
99 uint256 indexOfWinner = _randomness % players.length;
100 recentWinner = players[indexOfWinner];
101 recentWinner.transfer(address(this).balance);
102
103 //reset
104
105 players = new address payable[](0);
106 lottery_state = LOTTERY_STATE.CLOSED;
107 randomness = _randomness;
108 }
109}
110
111{
112 "solidity.compileUsingRemoteVersion": "v0.8.0+commit.c7dfd78e",
113 "solidity.defaultCompiler": "remote",
114 "solidity.compileUsingLocalVersion": "d:\\Python projects\\Solidity dev\\demo\\smartcontract-lottery\\soljson-v0.8.0+commit.c7dfd78e.js"
115 // "solidity.compileUsingRemoteVersion": "v0.7.4+commit.3f05b770",
116 // "solidity.enableLocalNodeCompiler": false
117}
118
In the brownie-config.yaml, I tried all the versions of openzepplin contracts too from old to latest (4.4.0, 4.3.0,4.3.2 etc), but same error.
brownie-config.yaml
1Retrieving compiler information:
2Compiler using remote version: 'v0.8.0+commit.c7dfd78e', solidity version: 0.8.0+commit.c7dfd78e.Emscripten.clang
3PS D:\Python projects\Solidity dev\demo\smartcontract-lottery> brownie compile
4INFO: Could not find files for the given pattern(s).
5Brownie v1.17.2 - Python development framework for Ethereum
6
7Compiling contracts...
8 Solc version: 0.6.12
9 Optimizer: Enabled Runs: 200
10 EVM Version: Istanbul
11CompilerError: solc returned the following errors:
12
13C:/Users/rosne/.brownie/packages/OpenZeppelin/openzeppelin-contracts@4.3.0/contracts/access/Ownable.sol:3:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
14pragma solidity ^0.8.0;
15^---------------------^
16
17C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.8/VRFConsumerBase.sol:2:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
18pragma solidity ^0.8.0;
19^---------------------^
20
21PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
22// SPDX-License-Identifier: MIT
23pragma solidity ^0.6.0;
24
25import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
26import "@openzeppelin/contracts/access/Ownable.sol";
27import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
28
29contract Lottery is VRFConsumerBase, Ownable {
30 uint256 usdEntryFee;
31 address payable[] public players;
32 address payable public recentWinner;
33 uint256 public randomness;
34 AggregatorV3Interface internal ethUsdPriceFeed;
35 enum LOTTERY_STATE {
36 OPEN,
37 CLOSED,
38 CALCULATING_WINNER
39 }
40
41 LOTTERY_STATE public lottery_state;
42 uint256 public fee;
43 bytes32 public keyhash;
44
45 constructor(
46 address _priceFeedAddress,
47 address _vrfCoordinator,
48 address _link,
49 uint256 _fee,
50 bytes32 _keyhash
51 ) public VRFConsumerBase(_vrfCoordinator, _link) {
52 usdEntryFee = 50 * (10**18);
53 ethUsdPriceFeed = AggregatorV3Interface(_priceFeedAddress);
54 lottery_state = LOTTERY_STATE.CLOSED;
55 fee = _fee;
56 keyhash = _keyhash;
57 }
58
59 function enter() public payable {
60 //$50 min
61 require(lottery_state == LOTTERY_STATE.OPEN);
62 require(msg.value >= getEntranceFee(), "Not enough ETH!");
63 players.push(payable(msg.sender));
64 }
65
66 function getEntranceFee() public view returns (uint256) {
67 (, int256 price, , , ) = ethUsdPriceFeed.latestRoundData();
68 uint256 adjustedPrice = uint256(price) * 10**12; //18 decimals
69 //$50, 2000 ETH
70 //50/2000
71 //50*10000/2000
72 uint256 costToEnter = (usdEntryFee * 10**18) / adjustedPrice;
73 return costToEnter;
74 }
75
76 function startLottery() public onlyOwner {
77 require(
78 lottery_state == LOTTERY_STATE.CLOSED,
79 "cant start a new lottery yet"
80 );
81 lottery_state = LOTTERY_STATE.OPEN;
82 }
83
84 function endLottery() public onlyOwner {
85 lottery_state = LOTTERY_STATE.CALCULATING_WINNER;
86 bytes32 requestId = requestRandomness(keyhash, fee);
87 }
88
89 function FulfillRandomness(bytes32 _requestId, uint256 _randomness)
90 internal
91 override
92 {
93 require(
94 lottery_state == LOTTERY_STATE.CALCULATING_WINNER,
95 "you arent there yet!"
96 );
97
98 require(_randomness > 0, "random not found");
99 uint256 indexOfWinner = _randomness % players.length;
100 recentWinner = players[indexOfWinner];
101 recentWinner.transfer(address(this).balance);
102
103 //reset
104
105 players = new address payable[](0);
106 lottery_state = LOTTERY_STATE.CLOSED;
107 randomness = _randomness;
108 }
109}
110
111{
112 "solidity.compileUsingRemoteVersion": "v0.8.0+commit.c7dfd78e",
113 "solidity.defaultCompiler": "remote",
114 "solidity.compileUsingLocalVersion": "d:\\Python projects\\Solidity dev\\demo\\smartcontract-lottery\\soljson-v0.8.0+commit.c7dfd78e.js"
115 // "solidity.compileUsingRemoteVersion": "v0.7.4+commit.3f05b770",
116 // "solidity.enableLocalNodeCompiler": false
117}
118dependencies:
119 - smartcontractkit/chainlink-brownie-contracts@1.1.1
120 - OpenZeppelin/openzeppelin-contracts@4.3.0
121compiler:
122 solc:
123 remappings:
124 - '@chainlink=smartcontractkit/chainlink-brownie-contracts@0.2.1'
125 - '@openzeppelin=OpenZeppelin/openzeppelin-contracts@4.3.0'
126networks:
127 mainnet-fork:
128 eth_usd_price_feed: '0xaEA2808407B7319A31A383B6F8B60f04BCa23cE2'
129
I also tried to change the compiler in lottery.sol file with
1Retrieving compiler information:
2Compiler using remote version: 'v0.8.0+commit.c7dfd78e', solidity version: 0.8.0+commit.c7dfd78e.Emscripten.clang
3PS D:\Python projects\Solidity dev\demo\smartcontract-lottery> brownie compile
4INFO: Could not find files for the given pattern(s).
5Brownie v1.17.2 - Python development framework for Ethereum
6
7Compiling contracts...
8 Solc version: 0.6.12
9 Optimizer: Enabled Runs: 200
10 EVM Version: Istanbul
11CompilerError: solc returned the following errors:
12
13C:/Users/rosne/.brownie/packages/OpenZeppelin/openzeppelin-contracts@4.3.0/contracts/access/Ownable.sol:3:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
14pragma solidity ^0.8.0;
15^---------------------^
16
17C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.8/VRFConsumerBase.sol:2:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
18pragma solidity ^0.8.0;
19^---------------------^
20
21PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
22// SPDX-License-Identifier: MIT
23pragma solidity ^0.6.0;
24
25import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
26import "@openzeppelin/contracts/access/Ownable.sol";
27import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
28
29contract Lottery is VRFConsumerBase, Ownable {
30 uint256 usdEntryFee;
31 address payable[] public players;
32 address payable public recentWinner;
33 uint256 public randomness;
34 AggregatorV3Interface internal ethUsdPriceFeed;
35 enum LOTTERY_STATE {
36 OPEN,
37 CLOSED,
38 CALCULATING_WINNER
39 }
40
41 LOTTERY_STATE public lottery_state;
42 uint256 public fee;
43 bytes32 public keyhash;
44
45 constructor(
46 address _priceFeedAddress,
47 address _vrfCoordinator,
48 address _link,
49 uint256 _fee,
50 bytes32 _keyhash
51 ) public VRFConsumerBase(_vrfCoordinator, _link) {
52 usdEntryFee = 50 * (10**18);
53 ethUsdPriceFeed = AggregatorV3Interface(_priceFeedAddress);
54 lottery_state = LOTTERY_STATE.CLOSED;
55 fee = _fee;
56 keyhash = _keyhash;
57 }
58
59 function enter() public payable {
60 //$50 min
61 require(lottery_state == LOTTERY_STATE.OPEN);
62 require(msg.value >= getEntranceFee(), "Not enough ETH!");
63 players.push(payable(msg.sender));
64 }
65
66 function getEntranceFee() public view returns (uint256) {
67 (, int256 price, , , ) = ethUsdPriceFeed.latestRoundData();
68 uint256 adjustedPrice = uint256(price) * 10**12; //18 decimals
69 //$50, 2000 ETH
70 //50/2000
71 //50*10000/2000
72 uint256 costToEnter = (usdEntryFee * 10**18) / adjustedPrice;
73 return costToEnter;
74 }
75
76 function startLottery() public onlyOwner {
77 require(
78 lottery_state == LOTTERY_STATE.CLOSED,
79 "cant start a new lottery yet"
80 );
81 lottery_state = LOTTERY_STATE.OPEN;
82 }
83
84 function endLottery() public onlyOwner {
85 lottery_state = LOTTERY_STATE.CALCULATING_WINNER;
86 bytes32 requestId = requestRandomness(keyhash, fee);
87 }
88
89 function FulfillRandomness(bytes32 _requestId, uint256 _randomness)
90 internal
91 override
92 {
93 require(
94 lottery_state == LOTTERY_STATE.CALCULATING_WINNER,
95 "you arent there yet!"
96 );
97
98 require(_randomness > 0, "random not found");
99 uint256 indexOfWinner = _randomness % players.length;
100 recentWinner = players[indexOfWinner];
101 recentWinner.transfer(address(this).balance);
102
103 //reset
104
105 players = new address payable[](0);
106 lottery_state = LOTTERY_STATE.CLOSED;
107 randomness = _randomness;
108 }
109}
110
111{
112 "solidity.compileUsingRemoteVersion": "v0.8.0+commit.c7dfd78e",
113 "solidity.defaultCompiler": "remote",
114 "solidity.compileUsingLocalVersion": "d:\\Python projects\\Solidity dev\\demo\\smartcontract-lottery\\soljson-v0.8.0+commit.c7dfd78e.js"
115 // "solidity.compileUsingRemoteVersion": "v0.7.4+commit.3f05b770",
116 // "solidity.enableLocalNodeCompiler": false
117}
118dependencies:
119 - smartcontractkit/chainlink-brownie-contracts@1.1.1
120 - OpenZeppelin/openzeppelin-contracts@4.3.0
121compiler:
122 solc:
123 remappings:
124 - '@chainlink=smartcontractkit/chainlink-brownie-contracts@0.2.1'
125 - '@openzeppelin=OpenZeppelin/openzeppelin-contracts@4.3.0'
126networks:
127 mainnet-fork:
128 eth_usd_price_feed: '0xaEA2808407B7319A31A383B6F8B60f04BCa23cE2'
129// SPDX-License-Identifier: MIT
130pragma solidity ^0.8.0;
131
Now I get a different error. Completely lost here :(
terminal:
1Retrieving compiler information:
2Compiler using remote version: 'v0.8.0+commit.c7dfd78e', solidity version: 0.8.0+commit.c7dfd78e.Emscripten.clang
3PS D:\Python projects\Solidity dev\demo\smartcontract-lottery> brownie compile
4INFO: Could not find files for the given pattern(s).
5Brownie v1.17.2 - Python development framework for Ethereum
6
7Compiling contracts...
8 Solc version: 0.6.12
9 Optimizer: Enabled Runs: 200
10 EVM Version: Istanbul
11CompilerError: solc returned the following errors:
12
13C:/Users/rosne/.brownie/packages/OpenZeppelin/openzeppelin-contracts@4.3.0/contracts/access/Ownable.sol:3:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
14pragma solidity ^0.8.0;
15^---------------------^
16
17C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.8/VRFConsumerBase.sol:2:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
18pragma solidity ^0.8.0;
19^---------------------^
20
21PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
22// SPDX-License-Identifier: MIT
23pragma solidity ^0.6.0;
24
25import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
26import "@openzeppelin/contracts/access/Ownable.sol";
27import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
28
29contract Lottery is VRFConsumerBase, Ownable {
30 uint256 usdEntryFee;
31 address payable[] public players;
32 address payable public recentWinner;
33 uint256 public randomness;
34 AggregatorV3Interface internal ethUsdPriceFeed;
35 enum LOTTERY_STATE {
36 OPEN,
37 CLOSED,
38 CALCULATING_WINNER
39 }
40
41 LOTTERY_STATE public lottery_state;
42 uint256 public fee;
43 bytes32 public keyhash;
44
45 constructor(
46 address _priceFeedAddress,
47 address _vrfCoordinator,
48 address _link,
49 uint256 _fee,
50 bytes32 _keyhash
51 ) public VRFConsumerBase(_vrfCoordinator, _link) {
52 usdEntryFee = 50 * (10**18);
53 ethUsdPriceFeed = AggregatorV3Interface(_priceFeedAddress);
54 lottery_state = LOTTERY_STATE.CLOSED;
55 fee = _fee;
56 keyhash = _keyhash;
57 }
58
59 function enter() public payable {
60 //$50 min
61 require(lottery_state == LOTTERY_STATE.OPEN);
62 require(msg.value >= getEntranceFee(), "Not enough ETH!");
63 players.push(payable(msg.sender));
64 }
65
66 function getEntranceFee() public view returns (uint256) {
67 (, int256 price, , , ) = ethUsdPriceFeed.latestRoundData();
68 uint256 adjustedPrice = uint256(price) * 10**12; //18 decimals
69 //$50, 2000 ETH
70 //50/2000
71 //50*10000/2000
72 uint256 costToEnter = (usdEntryFee * 10**18) / adjustedPrice;
73 return costToEnter;
74 }
75
76 function startLottery() public onlyOwner {
77 require(
78 lottery_state == LOTTERY_STATE.CLOSED,
79 "cant start a new lottery yet"
80 );
81 lottery_state = LOTTERY_STATE.OPEN;
82 }
83
84 function endLottery() public onlyOwner {
85 lottery_state = LOTTERY_STATE.CALCULATING_WINNER;
86 bytes32 requestId = requestRandomness(keyhash, fee);
87 }
88
89 function FulfillRandomness(bytes32 _requestId, uint256 _randomness)
90 internal
91 override
92 {
93 require(
94 lottery_state == LOTTERY_STATE.CALCULATING_WINNER,
95 "you arent there yet!"
96 );
97
98 require(_randomness > 0, "random not found");
99 uint256 indexOfWinner = _randomness % players.length;
100 recentWinner = players[indexOfWinner];
101 recentWinner.transfer(address(this).balance);
102
103 //reset
104
105 players = new address payable[](0);
106 lottery_state = LOTTERY_STATE.CLOSED;
107 randomness = _randomness;
108 }
109}
110
111{
112 "solidity.compileUsingRemoteVersion": "v0.8.0+commit.c7dfd78e",
113 "solidity.defaultCompiler": "remote",
114 "solidity.compileUsingLocalVersion": "d:\\Python projects\\Solidity dev\\demo\\smartcontract-lottery\\soljson-v0.8.0+commit.c7dfd78e.js"
115 // "solidity.compileUsingRemoteVersion": "v0.7.4+commit.3f05b770",
116 // "solidity.enableLocalNodeCompiler": false
117}
118dependencies:
119 - smartcontractkit/chainlink-brownie-contracts@1.1.1
120 - OpenZeppelin/openzeppelin-contracts@4.3.0
121compiler:
122 solc:
123 remappings:
124 - '@chainlink=smartcontractkit/chainlink-brownie-contracts@0.2.1'
125 - '@openzeppelin=OpenZeppelin/openzeppelin-contracts@4.3.0'
126networks:
127 mainnet-fork:
128 eth_usd_price_feed: '0xaEA2808407B7319A31A383B6F8B60f04BCa23cE2'
129// SPDX-License-Identifier: MIT
130pragma solidity ^0.8.0;
131INFO: Could not find files for the given pattern(s).
132Brownie v1.17.2 - Python development framework for Ethereum
133
134Compiling contracts...
135 Solc version: 0.8.11
136 Optimizer: Enabled Runs: 200
137 EVM Version: Istanbul
138CompilerError: solc returned the following errors:
139
140ParserError: Source file requires different compiler version (current compiler is 0.8.11+commit.d7f03943.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
141 --> C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol:2:1:
142 |
1432 | pragma solidity ^0.6.0;
144 | ^^^^^^^^^^^^^^^^^^^^^^^
145
146PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
147
I am very new to programing in solidity and this is the first course I am following, I don't want to give up so easily, any help is much appreciated.
ANSWER
Answered 2022-Jan-02 at 03:09i had the same issue. i had this compiler setting:
1Retrieving compiler information:
2Compiler using remote version: 'v0.8.0+commit.c7dfd78e', solidity version: 0.8.0+commit.c7dfd78e.Emscripten.clang
3PS D:\Python projects\Solidity dev\demo\smartcontract-lottery> brownie compile
4INFO: Could not find files for the given pattern(s).
5Brownie v1.17.2 - Python development framework for Ethereum
6
7Compiling contracts...
8 Solc version: 0.6.12
9 Optimizer: Enabled Runs: 200
10 EVM Version: Istanbul
11CompilerError: solc returned the following errors:
12
13C:/Users/rosne/.brownie/packages/OpenZeppelin/openzeppelin-contracts@4.3.0/contracts/access/Ownable.sol:3:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
14pragma solidity ^0.8.0;
15^---------------------^
16
17C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.8/VRFConsumerBase.sol:2:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
18pragma solidity ^0.8.0;
19^---------------------^
20
21PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
22// SPDX-License-Identifier: MIT
23pragma solidity ^0.6.0;
24
25import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
26import "@openzeppelin/contracts/access/Ownable.sol";
27import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
28
29contract Lottery is VRFConsumerBase, Ownable {
30 uint256 usdEntryFee;
31 address payable[] public players;
32 address payable public recentWinner;
33 uint256 public randomness;
34 AggregatorV3Interface internal ethUsdPriceFeed;
35 enum LOTTERY_STATE {
36 OPEN,
37 CLOSED,
38 CALCULATING_WINNER
39 }
40
41 LOTTERY_STATE public lottery_state;
42 uint256 public fee;
43 bytes32 public keyhash;
44
45 constructor(
46 address _priceFeedAddress,
47 address _vrfCoordinator,
48 address _link,
49 uint256 _fee,
50 bytes32 _keyhash
51 ) public VRFConsumerBase(_vrfCoordinator, _link) {
52 usdEntryFee = 50 * (10**18);
53 ethUsdPriceFeed = AggregatorV3Interface(_priceFeedAddress);
54 lottery_state = LOTTERY_STATE.CLOSED;
55 fee = _fee;
56 keyhash = _keyhash;
57 }
58
59 function enter() public payable {
60 //$50 min
61 require(lottery_state == LOTTERY_STATE.OPEN);
62 require(msg.value >= getEntranceFee(), "Not enough ETH!");
63 players.push(payable(msg.sender));
64 }
65
66 function getEntranceFee() public view returns (uint256) {
67 (, int256 price, , , ) = ethUsdPriceFeed.latestRoundData();
68 uint256 adjustedPrice = uint256(price) * 10**12; //18 decimals
69 //$50, 2000 ETH
70 //50/2000
71 //50*10000/2000
72 uint256 costToEnter = (usdEntryFee * 10**18) / adjustedPrice;
73 return costToEnter;
74 }
75
76 function startLottery() public onlyOwner {
77 require(
78 lottery_state == LOTTERY_STATE.CLOSED,
79 "cant start a new lottery yet"
80 );
81 lottery_state = LOTTERY_STATE.OPEN;
82 }
83
84 function endLottery() public onlyOwner {
85 lottery_state = LOTTERY_STATE.CALCULATING_WINNER;
86 bytes32 requestId = requestRandomness(keyhash, fee);
87 }
88
89 function FulfillRandomness(bytes32 _requestId, uint256 _randomness)
90 internal
91 override
92 {
93 require(
94 lottery_state == LOTTERY_STATE.CALCULATING_WINNER,
95 "you arent there yet!"
96 );
97
98 require(_randomness > 0, "random not found");
99 uint256 indexOfWinner = _randomness % players.length;
100 recentWinner = players[indexOfWinner];
101 recentWinner.transfer(address(this).balance);
102
103 //reset
104
105 players = new address payable[](0);
106 lottery_state = LOTTERY_STATE.CLOSED;
107 randomness = _randomness;
108 }
109}
110
111{
112 "solidity.compileUsingRemoteVersion": "v0.8.0+commit.c7dfd78e",
113 "solidity.defaultCompiler": "remote",
114 "solidity.compileUsingLocalVersion": "d:\\Python projects\\Solidity dev\\demo\\smartcontract-lottery\\soljson-v0.8.0+commit.c7dfd78e.js"
115 // "solidity.compileUsingRemoteVersion": "v0.7.4+commit.3f05b770",
116 // "solidity.enableLocalNodeCompiler": false
117}
118dependencies:
119 - smartcontractkit/chainlink-brownie-contracts@1.1.1
120 - OpenZeppelin/openzeppelin-contracts@4.3.0
121compiler:
122 solc:
123 remappings:
124 - '@chainlink=smartcontractkit/chainlink-brownie-contracts@0.2.1'
125 - '@openzeppelin=OpenZeppelin/openzeppelin-contracts@4.3.0'
126networks:
127 mainnet-fork:
128 eth_usd_price_feed: '0xaEA2808407B7319A31A383B6F8B60f04BCa23cE2'
129// SPDX-License-Identifier: MIT
130pragma solidity ^0.8.0;
131INFO: Could not find files for the given pattern(s).
132Brownie v1.17.2 - Python development framework for Ethereum
133
134Compiling contracts...
135 Solc version: 0.8.11
136 Optimizer: Enabled Runs: 200
137 EVM Version: Istanbul
138CompilerError: solc returned the following errors:
139
140ParserError: Source file requires different compiler version (current compiler is 0.8.11+commit.d7f03943.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
141 --> C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol:2:1:
142 |
1432 | pragma solidity ^0.6.0;
144 | ^^^^^^^^^^^^^^^^^^^^^^^
145
146PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
147pragma solidity >=0.4.22 <0.9.0;
148
Since we are importing from openzeppelin
, I visied github repo and saw that it uses pragma solidity ^0.8.0;
So changed my setting to
1Retrieving compiler information:
2Compiler using remote version: 'v0.8.0+commit.c7dfd78e', solidity version: 0.8.0+commit.c7dfd78e.Emscripten.clang
3PS D:\Python projects\Solidity dev\demo\smartcontract-lottery> brownie compile
4INFO: Could not find files for the given pattern(s).
5Brownie v1.17.2 - Python development framework for Ethereum
6
7Compiling contracts...
8 Solc version: 0.6.12
9 Optimizer: Enabled Runs: 200
10 EVM Version: Istanbul
11CompilerError: solc returned the following errors:
12
13C:/Users/rosne/.brownie/packages/OpenZeppelin/openzeppelin-contracts@4.3.0/contracts/access/Ownable.sol:3:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
14pragma solidity ^0.8.0;
15^---------------------^
16
17C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.8/VRFConsumerBase.sol:2:1: ParserError: Source file requires different compiler version (current compiler is 0.6.12+commit.27d51765.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
18pragma solidity ^0.8.0;
19^---------------------^
20
21PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
22// SPDX-License-Identifier: MIT
23pragma solidity ^0.6.0;
24
25import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
26import "@openzeppelin/contracts/access/Ownable.sol";
27import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
28
29contract Lottery is VRFConsumerBase, Ownable {
30 uint256 usdEntryFee;
31 address payable[] public players;
32 address payable public recentWinner;
33 uint256 public randomness;
34 AggregatorV3Interface internal ethUsdPriceFeed;
35 enum LOTTERY_STATE {
36 OPEN,
37 CLOSED,
38 CALCULATING_WINNER
39 }
40
41 LOTTERY_STATE public lottery_state;
42 uint256 public fee;
43 bytes32 public keyhash;
44
45 constructor(
46 address _priceFeedAddress,
47 address _vrfCoordinator,
48 address _link,
49 uint256 _fee,
50 bytes32 _keyhash
51 ) public VRFConsumerBase(_vrfCoordinator, _link) {
52 usdEntryFee = 50 * (10**18);
53 ethUsdPriceFeed = AggregatorV3Interface(_priceFeedAddress);
54 lottery_state = LOTTERY_STATE.CLOSED;
55 fee = _fee;
56 keyhash = _keyhash;
57 }
58
59 function enter() public payable {
60 //$50 min
61 require(lottery_state == LOTTERY_STATE.OPEN);
62 require(msg.value >= getEntranceFee(), "Not enough ETH!");
63 players.push(payable(msg.sender));
64 }
65
66 function getEntranceFee() public view returns (uint256) {
67 (, int256 price, , , ) = ethUsdPriceFeed.latestRoundData();
68 uint256 adjustedPrice = uint256(price) * 10**12; //18 decimals
69 //$50, 2000 ETH
70 //50/2000
71 //50*10000/2000
72 uint256 costToEnter = (usdEntryFee * 10**18) / adjustedPrice;
73 return costToEnter;
74 }
75
76 function startLottery() public onlyOwner {
77 require(
78 lottery_state == LOTTERY_STATE.CLOSED,
79 "cant start a new lottery yet"
80 );
81 lottery_state = LOTTERY_STATE.OPEN;
82 }
83
84 function endLottery() public onlyOwner {
85 lottery_state = LOTTERY_STATE.CALCULATING_WINNER;
86 bytes32 requestId = requestRandomness(keyhash, fee);
87 }
88
89 function FulfillRandomness(bytes32 _requestId, uint256 _randomness)
90 internal
91 override
92 {
93 require(
94 lottery_state == LOTTERY_STATE.CALCULATING_WINNER,
95 "you arent there yet!"
96 );
97
98 require(_randomness > 0, "random not found");
99 uint256 indexOfWinner = _randomness % players.length;
100 recentWinner = players[indexOfWinner];
101 recentWinner.transfer(address(this).balance);
102
103 //reset
104
105 players = new address payable[](0);
106 lottery_state = LOTTERY_STATE.CLOSED;
107 randomness = _randomness;
108 }
109}
110
111{
112 "solidity.compileUsingRemoteVersion": "v0.8.0+commit.c7dfd78e",
113 "solidity.defaultCompiler": "remote",
114 "solidity.compileUsingLocalVersion": "d:\\Python projects\\Solidity dev\\demo\\smartcontract-lottery\\soljson-v0.8.0+commit.c7dfd78e.js"
115 // "solidity.compileUsingRemoteVersion": "v0.7.4+commit.3f05b770",
116 // "solidity.enableLocalNodeCompiler": false
117}
118dependencies:
119 - smartcontractkit/chainlink-brownie-contracts@1.1.1
120 - OpenZeppelin/openzeppelin-contracts@4.3.0
121compiler:
122 solc:
123 remappings:
124 - '@chainlink=smartcontractkit/chainlink-brownie-contracts@0.2.1'
125 - '@openzeppelin=OpenZeppelin/openzeppelin-contracts@4.3.0'
126networks:
127 mainnet-fork:
128 eth_usd_price_feed: '0xaEA2808407B7319A31A383B6F8B60f04BCa23cE2'
129// SPDX-License-Identifier: MIT
130pragma solidity ^0.8.0;
131INFO: Could not find files for the given pattern(s).
132Brownie v1.17.2 - Python development framework for Ethereum
133
134Compiling contracts...
135 Solc version: 0.8.11
136 Optimizer: Enabled Runs: 200
137 EVM Version: Istanbul
138CompilerError: solc returned the following errors:
139
140ParserError: Source file requires different compiler version (current compiler is 0.8.11+commit.d7f03943.Windows.msvc) - note that nightly builds are considered to be strictly less than the released version
141 --> C:/Users/rosne/.brownie/packages/smartcontractkit/chainlink-brownie-contracts@0.2.1/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol:2:1:
142 |
1432 | pragma solidity ^0.6.0;
144 | ^^^^^^^^^^^^^^^^^^^^^^^
145
146PS D:\Python projects\Solidity dev\demo\smartcontract-lottery>
147pragma solidity >=0.4.22 <0.9.0;
148 pragma solidity >=0.4.22 <0.8.0;
149
QUESTION
How to delete an image saved in IPFS blockchain?
Asked 2022-Jan-28 at 04:56I am working on a blockcahin based image sharing website in ethereum
1function uploadImage(string memory _imgHASH,string memory _description ) public{
2 //making sure image ipfs hash exist
3 require(bytes(_imgHASH).length > 0);
4 //making sure that the image description exist
5 require(bytes(_description).length > 0);
6
7 require(msg.sender != address(0));
8
9 //increment image id
10 imageCount ++;
11
12 //add image to contract
13 images[imageCount] = Image(imageCount,_imgHASH,_description,0,msg.sender);
14
15
16 //trigger an image
17 emit ImageCreated(imageCount, _imgHASH, _description, 0, msg.sender);
18}
19
This is how you upload images but now I want user to delete images created by them how do i do it?
ANSWER
Answered 2022-Jan-10 at 15:28You cannot delete an image from IPFS the way you interact with the database. (giving the IPNS of the content and user sends an http request to delete it).
When you upload your content, you pin it to a node. Now the thing is the node that your content is pinned should be unpinned. So if you have a control over that node, If you started your own node, you unpin it and then ipfs will garbage collect it.
https://docs.ipfs.io/concepts/persistence/#garbage-collection
But if an image has been added and copied to another node, any person with the fingerprint can find it again. So whoever controls that node should unpin it.
QUESTION
Is it possible to call a ERC20 function inside a ERC721 contract?
Asked 2022-Jan-28 at 04:55What I am trying to achieve is calling a transferFrom
from ERC20 contract inside an ERC721 contract like this:
My ERC20 contract:
1pragma solidity ^0.7.0;
2import "../openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
3import "../openzeppelin-contracts/contracts/math/SafeMath.sol";
4
5contract ERC20Token is IERC20 {
6 using SafeMath for uint256;
7 bytes32[] public candidateList;
8
9 uint public totalTokens;
10 uint public balanceTokens;
11 uint public tokenPrice;
12
13 // what is the voter address?
14 // total tokens purchased
15 // tokens voted per candidate
16
17 struct voter {
18 address voterAddress;
19 uint tokensBought;
20 uint256[] tokensUsedPerCandidate;
21 }
22
23 mapping(address => voter) public voterInfo;
24
25 mapping(bytes32 => uint256) public votesReceived;
26
27 string public symbol;
28 string public name;
29 uint8 public decimals;
30
31 mapping(address => uint256) balances;
32 mapping(address => mapping(address => uint256)) allowed;
33
34 constructor(uint256 _totalTokens, uint256 _tokenPrice, bytes32[] memory _candidateNames) {
35 symbol = "NCToken";
36 name = "NCSOFT TOKEN";
37 decimals = 0;
38 totalTokens = _totalTokens;
39 balanceTokens = _totalTokens;
40 tokenPrice = _tokenPrice;
41 candidateList = _candidateNames;
42 emit Transfer(address(0), msg.sender, totalTokens);
43
44
45 function transferFrom(address from, address to, uint256 tokens) public override returns (bool) { //This is the function I am trying to call from ERC721 contract
46 balances[from] = SafeMath.sub(balances[from], tokens);
47 allowed[from][msg.sender] = SafeMath.sub(allowed[from][msg.sender], tokens);
48 balances[to] = SafeMath.add(balances[to], tokens);
49 emit Transfer(from, to, tokens);
50 return true;
51 }
52
53}
54
My ERC721 contract:
1pragma solidity ^0.7.0;
2import "../openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
3import "../openzeppelin-contracts/contracts/math/SafeMath.sol";
4
5contract ERC20Token is IERC20 {
6 using SafeMath for uint256;
7 bytes32[] public candidateList;
8
9 uint public totalTokens;
10 uint public balanceTokens;
11 uint public tokenPrice;
12
13 // what is the voter address?
14 // total tokens purchased
15 // tokens voted per candidate
16
17 struct voter {
18 address voterAddress;
19 uint tokensBought;
20 uint256[] tokensUsedPerCandidate;
21 }
22
23 mapping(address => voter) public voterInfo;
24
25 mapping(bytes32 => uint256) public votesReceived;
26
27 string public symbol;
28 string public name;
29 uint8 public decimals;
30
31 mapping(address => uint256) balances;
32 mapping(address => mapping(address => uint256)) allowed;
33
34 constructor(uint256 _totalTokens, uint256 _tokenPrice, bytes32[] memory _candidateNames) {
35 symbol = "NCToken";
36 name = "NCSOFT TOKEN";
37 decimals = 0;
38 totalTokens = _totalTokens;
39 balanceTokens = _totalTokens;
40 tokenPrice = _tokenPrice;
41 candidateList = _candidateNames;
42 emit Transfer(address(0), msg.sender, totalTokens);
43
44
45 function transferFrom(address from, address to, uint256 tokens) public override returns (bool) { //This is the function I am trying to call from ERC721 contract
46 balances[from] = SafeMath.sub(balances[from], tokens);
47 allowed[from][msg.sender] = SafeMath.sub(allowed[from][msg.sender], tokens);
48 balances[to] = SafeMath.add(balances[to], tokens);
49 emit Transfer(from, to, tokens);
50 return true;
51 }
52
53}
54// SPDX-License-Identifier: MIT
55pragma solidity ^0.7.0;
56
57import "../openzeppelin-contracts/contracts/token/ERC721/IERC721.sol";
58import "../openzeppelin-contracts/contracts/token/ERC721/ERC721.sol";
59import "../openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol";
60import "../openzeppelin-contracts/contracts/math/SafeMath.sol";
61import "../openzeppelin-contracts/contracts/utils/Address.sol";
62import "../openzeppelin-contracts/contracts/utils/Counters.sol";
63import "./ERC20Token.sol";
64
65contract NFTtoken is ERC721 {
66 using SafeMath for uint256;
67 using Address for address;
68 using Counters for Counters.Counter;
69 Counters.Counter private _tokenIds;
70
71 bytes32[] candidates = [bytes32('Rama'), bytes32('Nick'), bytes32('Jose')];
72 ERC20Token ERC20TokenContract = new ERC20Token(1000, 1, candidates); //instantiating an ERC20 contract
73
74
75 address payable public owner;
76 mapping(bytes4 => bool) supportedInterfaces;
77
78 mapping(uint256 => address) tokenOwners; //a mapping from NFT ID to the address that owns it
79 mapping(address => uint256) balances; //a mapping from NFT ID to the address that owns it
80 mapping(uint256 => address) allowance; //a mapping from NFT ID to approved address
81 mapping(address => mapping(address => bool)) operators; //Mapping from owner address to mapping of operator addresses.
82 // mapping (uint256 => string) idToUri;
83 uint8 public decimals;
84
85 uint256[] public allValidTokenIds;
86 mapping(uint256 => uint256) private allValidTokenIndex;
87 string[] public allNFTNames;
88
89 struct NFT {
90 //uint NFTID;
91 string name;
92 address creator;
93 }
94
95 mapping(address => NFT) public nftInfo;
96
97
98 constructor() ERC721("NC NFT example", "NCNFT") {
99 owner = msg.sender;
100 decimals = 0;
101 }
102
103
104 function mint(string calldata nftName) external payable {
105 uint256 newItemId = _tokenIds.current();
106 _mint(msg.sender, newItemId);
107
108 nftInfo[msg.sender].name = nftName;
109 nftInfo[msg.sender].creator = msg.sender;
110
111 allValidTokenIndex[newItemId] = allValidTokenIds.length;
112 allValidTokenIds.push(newItemId);
113 _tokenIds.increment();
114 }
115
116 function transferNFT(address from, address to, uint256 tokenId) public returns (bool){
117 transferFrom(from, to, tokenId);
118 ERC20TokenContract.transferFrom(to, nftInfo[from].creator, 10);
119//<-----***********This is throwing an error! I am trying to call ERC20Token.transferFrom.
120 }
121
122 function allNFTs() public view returns (uint256[] memory) {
123 return allValidTokenIds;
124 }
125}
126
127
Error Message when transferNFT
from ERC721 is called.
1pragma solidity ^0.7.0;
2import "../openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
3import "../openzeppelin-contracts/contracts/math/SafeMath.sol";
4
5contract ERC20Token is IERC20 {
6 using SafeMath for uint256;
7 bytes32[] public candidateList;
8
9 uint public totalTokens;
10 uint public balanceTokens;
11 uint public tokenPrice;
12
13 // what is the voter address?
14 // total tokens purchased
15 // tokens voted per candidate
16
17 struct voter {
18 address voterAddress;
19 uint tokensBought;
20 uint256[] tokensUsedPerCandidate;
21 }
22
23 mapping(address => voter) public voterInfo;
24
25 mapping(bytes32 => uint256) public votesReceived;
26
27 string public symbol;
28 string public name;
29 uint8 public decimals;
30
31 mapping(address => uint256) balances;
32 mapping(address => mapping(address => uint256)) allowed;
33
34 constructor(uint256 _totalTokens, uint256 _tokenPrice, bytes32[] memory _candidateNames) {
35 symbol = "NCToken";
36 name = "NCSOFT TOKEN";
37 decimals = 0;
38 totalTokens = _totalTokens;
39 balanceTokens = _totalTokens;
40 tokenPrice = _tokenPrice;
41 candidateList = _candidateNames;
42 emit Transfer(address(0), msg.sender, totalTokens);
43
44
45 function transferFrom(address from, address to, uint256 tokens) public override returns (bool) { //This is the function I am trying to call from ERC721 contract
46 balances[from] = SafeMath.sub(balances[from], tokens);
47 allowed[from][msg.sender] = SafeMath.sub(allowed[from][msg.sender], tokens);
48 balances[to] = SafeMath.add(balances[to], tokens);
49 emit Transfer(from, to, tokens);
50 return true;
51 }
52
53}
54// SPDX-License-Identifier: MIT
55pragma solidity ^0.7.0;
56
57import "../openzeppelin-contracts/contracts/token/ERC721/IERC721.sol";
58import "../openzeppelin-contracts/contracts/token/ERC721/ERC721.sol";
59import "../openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol";
60import "../openzeppelin-contracts/contracts/math/SafeMath.sol";
61import "../openzeppelin-contracts/contracts/utils/Address.sol";
62import "../openzeppelin-contracts/contracts/utils/Counters.sol";
63import "./ERC20Token.sol";
64
65contract NFTtoken is ERC721 {
66 using SafeMath for uint256;
67 using Address for address;
68 using Counters for Counters.Counter;
69 Counters.Counter private _tokenIds;
70
71 bytes32[] candidates = [bytes32('Rama'), bytes32('Nick'), bytes32('Jose')];
72 ERC20Token ERC20TokenContract = new ERC20Token(1000, 1, candidates); //instantiating an ERC20 contract
73
74
75 address payable public owner;
76 mapping(bytes4 => bool) supportedInterfaces;
77
78 mapping(uint256 => address) tokenOwners; //a mapping from NFT ID to the address that owns it
79 mapping(address => uint256) balances; //a mapping from NFT ID to the address that owns it
80 mapping(uint256 => address) allowance; //a mapping from NFT ID to approved address
81 mapping(address => mapping(address => bool)) operators; //Mapping from owner address to mapping of operator addresses.
82 // mapping (uint256 => string) idToUri;
83 uint8 public decimals;
84
85 uint256[] public allValidTokenIds;
86 mapping(uint256 => uint256) private allValidTokenIndex;
87 string[] public allNFTNames;
88
89 struct NFT {
90 //uint NFTID;
91 string name;
92 address creator;
93 }
94
95 mapping(address => NFT) public nftInfo;
96
97
98 constructor() ERC721("NC NFT example", "NCNFT") {
99 owner = msg.sender;
100 decimals = 0;
101 }
102
103
104 function mint(string calldata nftName) external payable {
105 uint256 newItemId = _tokenIds.current();
106 _mint(msg.sender, newItemId);
107
108 nftInfo[msg.sender].name = nftName;
109 nftInfo[msg.sender].creator = msg.sender;
110
111 allValidTokenIndex[newItemId] = allValidTokenIds.length;
112 allValidTokenIds.push(newItemId);
113 _tokenIds.increment();
114 }
115
116 function transferNFT(address from, address to, uint256 tokenId) public returns (bool){
117 transferFrom(from, to, tokenId);
118 ERC20TokenContract.transferFrom(to, nftInfo[from].creator, 10);
119//<-----***********This is throwing an error! I am trying to call ERC20Token.transferFrom.
120 }
121
122 function allNFTs() public view returns (uint256[] memory) {
123 return allValidTokenIds;
124 }
125}
126
127MetaMask - RPC Error: [ethjs-query] while formatting outputs from RPC '{"value":{"code":-32603,"data":{"message":"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token","code":-32000,"data":{"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f":{"error":"revert","program_counter":7889,"return":"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000","reason":"ERC721: operator query for nonexistent token"},"stack":"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\n at Function.RuntimeError.fromResults (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\utils\\runtimeerror.js:94:13)\n at BlockchainDouble.processBlock (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\blockchain_double.js:627:24)\n at runMicrotasks (<anonymous>)\n at processTicksAndRejections (internal/process/task_queues.js:93:5)","name":"RuntimeError"}}}}'
128{code: -32603, message: `[ethjs-query] while formatting outputs from RPC '{…/task_queues.js:93:5)","name":"RuntimeError"}}}}'`}
129code: -32603
130message: "[ethjs-query] while formatting outputs from RPC '{\"value\":{\"code\":-32603,\"data\":{\"message\":\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\",\"code\":-32000,\"data\":{\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\":{\"error\":\"revert\",\"program_counter\":7889,\"return\":\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\",\"reason\":\"ERC721: operator query for nonexistent token\"},\"stack\":\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\n at Function.RuntimeError.fromResults (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\utils\\\\runtimeerror.js:94:13)\\n at BlockchainDouble.processBlock (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\blockchain_double.js:627:24)\\n at runMicrotasks (<anonymous>)\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\",\"name\":\"RuntimeError\"}}}}'"
131[[Prototype]]: Object
132
1pragma solidity ^0.7.0;
2import "../openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
3import "../openzeppelin-contracts/contracts/math/SafeMath.sol";
4
5contract ERC20Token is IERC20 {
6 using SafeMath for uint256;
7 bytes32[] public candidateList;
8
9 uint public totalTokens;
10 uint public balanceTokens;
11 uint public tokenPrice;
12
13 // what is the voter address?
14 // total tokens purchased
15 // tokens voted per candidate
16
17 struct voter {
18 address voterAddress;
19 uint tokensBought;
20 uint256[] tokensUsedPerCandidate;
21 }
22
23 mapping(address => voter) public voterInfo;
24
25 mapping(bytes32 => uint256) public votesReceived;
26
27 string public symbol;
28 string public name;
29 uint8 public decimals;
30
31 mapping(address => uint256) balances;
32 mapping(address => mapping(address => uint256)) allowed;
33
34 constructor(uint256 _totalTokens, uint256 _tokenPrice, bytes32[] memory _candidateNames) {
35 symbol = "NCToken";
36 name = "NCSOFT TOKEN";
37 decimals = 0;
38 totalTokens = _totalTokens;
39 balanceTokens = _totalTokens;
40 tokenPrice = _tokenPrice;
41 candidateList = _candidateNames;
42 emit Transfer(address(0), msg.sender, totalTokens);
43
44
45 function transferFrom(address from, address to, uint256 tokens) public override returns (bool) { //This is the function I am trying to call from ERC721 contract
46 balances[from] = SafeMath.sub(balances[from], tokens);
47 allowed[from][msg.sender] = SafeMath.sub(allowed[from][msg.sender], tokens);
48 balances[to] = SafeMath.add(balances[to], tokens);
49 emit Transfer(from, to, tokens);
50 return true;
51 }
52
53}
54// SPDX-License-Identifier: MIT
55pragma solidity ^0.7.0;
56
57import "../openzeppelin-contracts/contracts/token/ERC721/IERC721.sol";
58import "../openzeppelin-contracts/contracts/token/ERC721/ERC721.sol";
59import "../openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol";
60import "../openzeppelin-contracts/contracts/math/SafeMath.sol";
61import "../openzeppelin-contracts/contracts/utils/Address.sol";
62import "../openzeppelin-contracts/contracts/utils/Counters.sol";
63import "./ERC20Token.sol";
64
65contract NFTtoken is ERC721 {
66 using SafeMath for uint256;
67 using Address for address;
68 using Counters for Counters.Counter;
69 Counters.Counter private _tokenIds;
70
71 bytes32[] candidates = [bytes32('Rama'), bytes32('Nick'), bytes32('Jose')];
72 ERC20Token ERC20TokenContract = new ERC20Token(1000, 1, candidates); //instantiating an ERC20 contract
73
74
75 address payable public owner;
76 mapping(bytes4 => bool) supportedInterfaces;
77
78 mapping(uint256 => address) tokenOwners; //a mapping from NFT ID to the address that owns it
79 mapping(address => uint256) balances; //a mapping from NFT ID to the address that owns it
80 mapping(uint256 => address) allowance; //a mapping from NFT ID to approved address
81 mapping(address => mapping(address => bool)) operators; //Mapping from owner address to mapping of operator addresses.
82 // mapping (uint256 => string) idToUri;
83 uint8 public decimals;
84
85 uint256[] public allValidTokenIds;
86 mapping(uint256 => uint256) private allValidTokenIndex;
87 string[] public allNFTNames;
88
89 struct NFT {
90 //uint NFTID;
91 string name;
92 address creator;
93 }
94
95 mapping(address => NFT) public nftInfo;
96
97
98 constructor() ERC721("NC NFT example", "NCNFT") {
99 owner = msg.sender;
100 decimals = 0;
101 }
102
103
104 function mint(string calldata nftName) external payable {
105 uint256 newItemId = _tokenIds.current();
106 _mint(msg.sender, newItemId);
107
108 nftInfo[msg.sender].name = nftName;
109 nftInfo[msg.sender].creator = msg.sender;
110
111 allValidTokenIndex[newItemId] = allValidTokenIds.length;
112 allValidTokenIds.push(newItemId);
113 _tokenIds.increment();
114 }
115
116 function transferNFT(address from, address to, uint256 tokenId) public returns (bool){
117 transferFrom(from, to, tokenId);
118 ERC20TokenContract.transferFrom(to, nftInfo[from].creator, 10);
119//<-----***********This is throwing an error! I am trying to call ERC20Token.transferFrom.
120 }
121
122 function allNFTs() public view returns (uint256[] memory) {
123 return allValidTokenIds;
124 }
125}
126
127MetaMask - RPC Error: [ethjs-query] while formatting outputs from RPC '{"value":{"code":-32603,"data":{"message":"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token","code":-32000,"data":{"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f":{"error":"revert","program_counter":7889,"return":"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000","reason":"ERC721: operator query for nonexistent token"},"stack":"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\n at Function.RuntimeError.fromResults (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\utils\\runtimeerror.js:94:13)\n at BlockchainDouble.processBlock (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\blockchain_double.js:627:24)\n at runMicrotasks (<anonymous>)\n at processTicksAndRejections (internal/process/task_queues.js:93:5)","name":"RuntimeError"}}}}'
128{code: -32603, message: `[ethjs-query] while formatting outputs from RPC '{…/task_queues.js:93:5)","name":"RuntimeError"}}}}'`}
129code: -32603
130message: "[ethjs-query] while formatting outputs from RPC '{\"value\":{\"code\":-32603,\"data\":{\"message\":\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\",\"code\":-32000,\"data\":{\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\":{\"error\":\"revert\",\"program_counter\":7889,\"return\":\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\",\"reason\":\"ERC721: operator query for nonexistent token\"},\"stack\":\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\n at Function.RuntimeError.fromResults (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\utils\\\\runtimeerror.js:94:13)\\n at BlockchainDouble.processBlock (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\blockchain_double.js:627:24)\\n at runMicrotasks (<anonymous>)\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\",\"name\":\"RuntimeError\"}}}}'"
131[[Prototype]]: Object
132localhost/:1 Uncaught (in promise)
133{code: -32603, message: `[ethjs-query] while formatting outputs from RPC '{…/task_queues.js:93:5)","name":"RuntimeError"}}}}'`, stack: '{\n "code": -32603,\n "message": "[ethjs-query] wh…gaeaoehlefnkodbefgpgknn/background-0.js:1:216902)'}
134code: -32603
135message: "[ethjs-query] while formatting outputs from RPC '{\"value\":{\"code\":-32603,\"data\":{\"message\":\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\",\"code\":-32000,\"data\":{\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\":{\"error\":\"revert\",\"program_counter\":7889,\"return\":\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\",\"reason\":\"ERC721: operator query for nonexistent token\"},\"stack\":\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\n at Function.RuntimeError.fromResults (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\utils\\\\runtimeerror.js:94:13)\\n at BlockchainDouble.processBlock (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\blockchain_double.js:627:24)\\n at runMicrotasks (<anonymous>)\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\",\"name\":\"RuntimeError\"}}}}'"
136stack: "{\n \"code\": -32603,\n \"message\": \"[ethjs-query] while formatting outputs from RPC '{\\\"value\\\":{\\\"code\\\":-32603,\\\"data\\\":{\\\"message\\\":\\\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\\",\\\"code\\\":-32000,\\\"data\\\":{\\\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\\\":{\\\"error\\\":\\\"revert\\\",\\\"program_counter\\\":7889,\\\"return\\\":\\\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\\\",\\\"reason\\\":\\\"ERC721: operator query for nonexistent token\\\"},\\\"stack\\\":\\\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\\\n at Function.RuntimeError.fromResults (C:\\\\\\\\Program Files\\\\\\\\WindowsApps\\\\\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\\\\\app\\\\\\\\resources\\\\\\\\static\\\\\\\\node\\\\\\\\node_modules\\\\\\\\ganache-core\\\\\\\\lib\\\\\\\\utils\\\\\\\\runtimeerror.js:94:13)\\\\n at BlockchainDouble.processBlock (C:\\\\\\\\Program Files\\\\\\\\WindowsApps\\\\\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\\\\\app\\\\\\\\resources\\\\\\\\static\\\\\\\\node\\\\\\\\node_modules\\\\\\\\ganache-core\\\\\\\\lib\\\\\\\\blockchain_double.js:627:24)\\\\n at runMicrotasks (<anonymous>)\\\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\\\",\\\"name\\\":\\\"RuntimeError\\\"}}}}'\",\n \"stack\": \"Error: [ethjs-query] while formatting outputs from RPC '{\\\"value\\\":{\\\"code\\\":-32603,\\\"data\\\":{\\\"message\\\":\\\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\\",\\\"code\\\":-32000,\\\"data\\\":{\\\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\\\":{\\\"error\\\":\\\"revert\\\",\\\"program_counter\\\":7889,\\\"return\\\":\\\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\\\",\\\"reason\\\":\\\"ERC721: operator query for nonexistent token\\\"},\\\"stack\\\":\\\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\\\n at Function.RuntimeError.fromResults (C:\\\\\\\\Program Files\\\\\\\\WindowsApps\\\\\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\\\\\app\\\\\\\\resources\\\\\\\\static\\\\\\\\node\\\\\\\\node_modules\\\\\\\\ganache-core\\\\\\\\lib\\\\\\\\utils\\\\\\\\runtimeerror.js:94:13)\\\\n at BlockchainDouble.processBlock (C:\\\\\\\\Program Files\\\\\\\\WindowsApps\\\\\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\\\\\app\\\\\\\\resources\\\\\\\\static\\\\\\\\node\\\\\\\\node_modules\\\\\\\\ganache-core\\\\\\\\lib\\\\\\\\blockchain_double.js:627:24)\\\\n at runMicrotasks (<anonymous>)\\\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\\\",\\\"name\\\":\\\"RuntimeError\\\"}}}}'\\n at new i (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:148782)\\n at s (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146325)\\n at Object.internal (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146935)\\n at y.<anonymous> (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:210928)\\n at Object.h (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:35204)\\n at u (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:117610)\\n at y.a.emit (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:118146)\\n at y._setTransactionStatus (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:46740)\\n at y.setTxStatusFailed (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:45972)\\n at B._failTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:225990)\\n at B.approveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:217659)\\n at async B.updateAndApproveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:216902)\"\n}\n at new i (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:148782)\n at s (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146325)\n at Object.internal (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146935)\n at y.<anonymous> (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:210928)\n at Object.h (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:35204)\n at u (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:117610)\n at y.a.emit (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:118146)\n at y._setTransactionStatus (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:46740)\n at y.setTxStatusFailed (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:45972)\n at B._failTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:225990)\n at B.approveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:217659)\n at async B.updateAndApproveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:216902)"
137[[Prototype]]: Object
138setTimeout (async)
139(anonymous) @ inpage.js:1
140write @ inpage.js:1
141
This is my javascript file calling the functions from both contracts.
1pragma solidity ^0.7.0;
2import "../openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
3import "../openzeppelin-contracts/contracts/math/SafeMath.sol";
4
5contract ERC20Token is IERC20 {
6 using SafeMath for uint256;
7 bytes32[] public candidateList;
8
9 uint public totalTokens;
10 uint public balanceTokens;
11 uint public tokenPrice;
12
13 // what is the voter address?
14 // total tokens purchased
15 // tokens voted per candidate
16
17 struct voter {
18 address voterAddress;
19 uint tokensBought;
20 uint256[] tokensUsedPerCandidate;
21 }
22
23 mapping(address => voter) public voterInfo;
24
25 mapping(bytes32 => uint256) public votesReceived;
26
27 string public symbol;
28 string public name;
29 uint8 public decimals;
30
31 mapping(address => uint256) balances;
32 mapping(address => mapping(address => uint256)) allowed;
33
34 constructor(uint256 _totalTokens, uint256 _tokenPrice, bytes32[] memory _candidateNames) {
35 symbol = "NCToken";
36 name = "NCSOFT TOKEN";
37 decimals = 0;
38 totalTokens = _totalTokens;
39 balanceTokens = _totalTokens;
40 tokenPrice = _tokenPrice;
41 candidateList = _candidateNames;
42 emit Transfer(address(0), msg.sender, totalTokens);
43
44
45 function transferFrom(address from, address to, uint256 tokens) public override returns (bool) { //This is the function I am trying to call from ERC721 contract
46 balances[from] = SafeMath.sub(balances[from], tokens);
47 allowed[from][msg.sender] = SafeMath.sub(allowed[from][msg.sender], tokens);
48 balances[to] = SafeMath.add(balances[to], tokens);
49 emit Transfer(from, to, tokens);
50 return true;
51 }
52
53}
54// SPDX-License-Identifier: MIT
55pragma solidity ^0.7.0;
56
57import "../openzeppelin-contracts/contracts/token/ERC721/IERC721.sol";
58import "../openzeppelin-contracts/contracts/token/ERC721/ERC721.sol";
59import "../openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol";
60import "../openzeppelin-contracts/contracts/math/SafeMath.sol";
61import "../openzeppelin-contracts/contracts/utils/Address.sol";
62import "../openzeppelin-contracts/contracts/utils/Counters.sol";
63import "./ERC20Token.sol";
64
65contract NFTtoken is ERC721 {
66 using SafeMath for uint256;
67 using Address for address;
68 using Counters for Counters.Counter;
69 Counters.Counter private _tokenIds;
70
71 bytes32[] candidates = [bytes32('Rama'), bytes32('Nick'), bytes32('Jose')];
72 ERC20Token ERC20TokenContract = new ERC20Token(1000, 1, candidates); //instantiating an ERC20 contract
73
74
75 address payable public owner;
76 mapping(bytes4 => bool) supportedInterfaces;
77
78 mapping(uint256 => address) tokenOwners; //a mapping from NFT ID to the address that owns it
79 mapping(address => uint256) balances; //a mapping from NFT ID to the address that owns it
80 mapping(uint256 => address) allowance; //a mapping from NFT ID to approved address
81 mapping(address => mapping(address => bool)) operators; //Mapping from owner address to mapping of operator addresses.
82 // mapping (uint256 => string) idToUri;
83 uint8 public decimals;
84
85 uint256[] public allValidTokenIds;
86 mapping(uint256 => uint256) private allValidTokenIndex;
87 string[] public allNFTNames;
88
89 struct NFT {
90 //uint NFTID;
91 string name;
92 address creator;
93 }
94
95 mapping(address => NFT) public nftInfo;
96
97
98 constructor() ERC721("NC NFT example", "NCNFT") {
99 owner = msg.sender;
100 decimals = 0;
101 }
102
103
104 function mint(string calldata nftName) external payable {
105 uint256 newItemId = _tokenIds.current();
106 _mint(msg.sender, newItemId);
107
108 nftInfo[msg.sender].name = nftName;
109 nftInfo[msg.sender].creator = msg.sender;
110
111 allValidTokenIndex[newItemId] = allValidTokenIds.length;
112 allValidTokenIds.push(newItemId);
113 _tokenIds.increment();
114 }
115
116 function transferNFT(address from, address to, uint256 tokenId) public returns (bool){
117 transferFrom(from, to, tokenId);
118 ERC20TokenContract.transferFrom(to, nftInfo[from].creator, 10);
119//<-----***********This is throwing an error! I am trying to call ERC20Token.transferFrom.
120 }
121
122 function allNFTs() public view returns (uint256[] memory) {
123 return allValidTokenIds;
124 }
125}
126
127MetaMask - RPC Error: [ethjs-query] while formatting outputs from RPC '{"value":{"code":-32603,"data":{"message":"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token","code":-32000,"data":{"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f":{"error":"revert","program_counter":7889,"return":"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000","reason":"ERC721: operator query for nonexistent token"},"stack":"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\n at Function.RuntimeError.fromResults (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\utils\\runtimeerror.js:94:13)\n at BlockchainDouble.processBlock (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\blockchain_double.js:627:24)\n at runMicrotasks (<anonymous>)\n at processTicksAndRejections (internal/process/task_queues.js:93:5)","name":"RuntimeError"}}}}'
128{code: -32603, message: `[ethjs-query] while formatting outputs from RPC '{…/task_queues.js:93:5)","name":"RuntimeError"}}}}'`}
129code: -32603
130message: "[ethjs-query] while formatting outputs from RPC '{\"value\":{\"code\":-32603,\"data\":{\"message\":\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\",\"code\":-32000,\"data\":{\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\":{\"error\":\"revert\",\"program_counter\":7889,\"return\":\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\",\"reason\":\"ERC721: operator query for nonexistent token\"},\"stack\":\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\n at Function.RuntimeError.fromResults (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\utils\\\\runtimeerror.js:94:13)\\n at BlockchainDouble.processBlock (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\blockchain_double.js:627:24)\\n at runMicrotasks (<anonymous>)\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\",\"name\":\"RuntimeError\"}}}}'"
131[[Prototype]]: Object
132localhost/:1 Uncaught (in promise)
133{code: -32603, message: `[ethjs-query] while formatting outputs from RPC '{…/task_queues.js:93:5)","name":"RuntimeError"}}}}'`, stack: '{\n "code": -32603,\n "message": "[ethjs-query] wh…gaeaoehlefnkodbefgpgknn/background-0.js:1:216902)'}
134code: -32603
135message: "[ethjs-query] while formatting outputs from RPC '{\"value\":{\"code\":-32603,\"data\":{\"message\":\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\",\"code\":-32000,\"data\":{\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\":{\"error\":\"revert\",\"program_counter\":7889,\"return\":\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\",\"reason\":\"ERC721: operator query for nonexistent token\"},\"stack\":\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\n at Function.RuntimeError.fromResults (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\utils\\\\runtimeerror.js:94:13)\\n at BlockchainDouble.processBlock (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\blockchain_double.js:627:24)\\n at runMicrotasks (<anonymous>)\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\",\"name\":\"RuntimeError\"}}}}'"
136stack: "{\n \"code\": -32603,\n \"message\": \"[ethjs-query] while formatting outputs from RPC '{\\\"value\\\":{\\\"code\\\":-32603,\\\"data\\\":{\\\"message\\\":\\\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\\",\\\"code\\\":-32000,\\\"data\\\":{\\\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\\\":{\\\"error\\\":\\\"revert\\\",\\\"program_counter\\\":7889,\\\"return\\\":\\\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\\\",\\\"reason\\\":\\\"ERC721: operator query for nonexistent token\\\"},\\\"stack\\\":\\\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\\\n at Function.RuntimeError.fromResults (C:\\\\\\\\Program Files\\\\\\\\WindowsApps\\\\\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\\\\\app\\\\\\\\resources\\\\\\\\static\\\\\\\\node\\\\\\\\node_modules\\\\\\\\ganache-core\\\\\\\\lib\\\\\\\\utils\\\\\\\\runtimeerror.js:94:13)\\\\n at BlockchainDouble.processBlock (C:\\\\\\\\Program Files\\\\\\\\WindowsApps\\\\\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\\\\\app\\\\\\\\resources\\\\\\\\static\\\\\\\\node\\\\\\\\node_modules\\\\\\\\ganache-core\\\\\\\\lib\\\\\\\\blockchain_double.js:627:24)\\\\n at runMicrotasks (<anonymous>)\\\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\\\",\\\"name\\\":\\\"RuntimeError\\\"}}}}'\",\n \"stack\": \"Error: [ethjs-query] while formatting outputs from RPC '{\\\"value\\\":{\\\"code\\\":-32603,\\\"data\\\":{\\\"message\\\":\\\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\\",\\\"code\\\":-32000,\\\"data\\\":{\\\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\\\":{\\\"error\\\":\\\"revert\\\",\\\"program_counter\\\":7889,\\\"return\\\":\\\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\\\",\\\"reason\\\":\\\"ERC721: operator query for nonexistent token\\\"},\\\"stack\\\":\\\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\\\n at Function.RuntimeError.fromResults (C:\\\\\\\\Program Files\\\\\\\\WindowsApps\\\\\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\\\\\app\\\\\\\\resources\\\\\\\\static\\\\\\\\node\\\\\\\\node_modules\\\\\\\\ganache-core\\\\\\\\lib\\\\\\\\utils\\\\\\\\runtimeerror.js:94:13)\\\\n at BlockchainDouble.processBlock (C:\\\\\\\\Program Files\\\\\\\\WindowsApps\\\\\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\\\\\app\\\\\\\\resources\\\\\\\\static\\\\\\\\node\\\\\\\\node_modules\\\\\\\\ganache-core\\\\\\\\lib\\\\\\\\blockchain_double.js:627:24)\\\\n at runMicrotasks (<anonymous>)\\\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\\\",\\\"name\\\":\\\"RuntimeError\\\"}}}}'\\n at new i (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:148782)\\n at s (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146325)\\n at Object.internal (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146935)\\n at y.<anonymous> (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:210928)\\n at Object.h (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:35204)\\n at u (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:117610)\\n at y.a.emit (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:118146)\\n at y._setTransactionStatus (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:46740)\\n at y.setTxStatusFailed (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:45972)\\n at B._failTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:225990)\\n at B.approveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:217659)\\n at async B.updateAndApproveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:216902)\"\n}\n at new i (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:148782)\n at s (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146325)\n at Object.internal (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146935)\n at y.<anonymous> (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:210928)\n at Object.h (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:35204)\n at u (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:117610)\n at y.a.emit (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:118146)\n at y._setTransactionStatus (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:46740)\n at y.setTxStatusFailed (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:45972)\n at B._failTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:225990)\n at B.approveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:217659)\n at async B.updateAndApproveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:216902)"
137[[Prototype]]: Object
138setTimeout (async)
139(anonymous) @ inpage.js:1
140write @ inpage.js:1
141// Import libraries we need.
142import { default as Web3} from 'web3';
143import { default as contract } from 'truffle-contract'
144
145import voting_artifacts from '../../build/contracts/Voting.json'
146import voting_artifacts2 from '../../build/contracts/DeedToken.json'
147
148window.App = {
149 start: function() {
150 var self = this;
151 self.transferNFT();
152 },
153transferNFT: function() {
154 NFTContract.deployed().then(function(contractInstance) {
155 let toAddress = $("#to-address").val();
156 let NFTid_temp = $("#nft-id").val();
157 let NFTid = NFTid_temp.substring(7);
158 contractInstance.transferFrom(web3.currentProvider.selectedAddress, toAddress, NFTid, {gas: 140000, from: web3.eth.accounts[0]});
159 })
160}
161}
162
163window.addEventListener('load', async function() {
164 if (window.ethereum) {
165 await window.ethereum.send('eth_requestAccounts');
166 window.web3 = new Web3(window.ethereum);
167 }
168 else {
169 console.warn("No web3 detected.");
170 window.web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:8545"));
171 }
172
173 App.start();
174});
175
ANSWER
Answered 2022-Jan-11 at 14:03In order to interact with an ERC20 token, you have to create an instance of it from the desired contract. You would need to import ERC20 to your nfts contracts, and then create an ERC20 token instance pointing to your token. It would be something like this:
1pragma solidity ^0.7.0;
2import "../openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
3import "../openzeppelin-contracts/contracts/math/SafeMath.sol";
4
5contract ERC20Token is IERC20 {
6 using SafeMath for uint256;
7 bytes32[] public candidateList;
8
9 uint public totalTokens;
10 uint public balanceTokens;
11 uint public tokenPrice;
12
13 // what is the voter address?
14 // total tokens purchased
15 // tokens voted per candidate
16
17 struct voter {
18 address voterAddress;
19 uint tokensBought;
20 uint256[] tokensUsedPerCandidate;
21 }
22
23 mapping(address => voter) public voterInfo;
24
25 mapping(bytes32 => uint256) public votesReceived;
26
27 string public symbol;
28 string public name;
29 uint8 public decimals;
30
31 mapping(address => uint256) balances;
32 mapping(address => mapping(address => uint256)) allowed;
33
34 constructor(uint256 _totalTokens, uint256 _tokenPrice, bytes32[] memory _candidateNames) {
35 symbol = "NCToken";
36 name = "NCSOFT TOKEN";
37 decimals = 0;
38 totalTokens = _totalTokens;
39 balanceTokens = _totalTokens;
40 tokenPrice = _tokenPrice;
41 candidateList = _candidateNames;
42 emit Transfer(address(0), msg.sender, totalTokens);
43
44
45 function transferFrom(address from, address to, uint256 tokens) public override returns (bool) { //This is the function I am trying to call from ERC721 contract
46 balances[from] = SafeMath.sub(balances[from], tokens);
47 allowed[from][msg.sender] = SafeMath.sub(allowed[from][msg.sender], tokens);
48 balances[to] = SafeMath.add(balances[to], tokens);
49 emit Transfer(from, to, tokens);
50 return true;
51 }
52
53}
54// SPDX-License-Identifier: MIT
55pragma solidity ^0.7.0;
56
57import "../openzeppelin-contracts/contracts/token/ERC721/IERC721.sol";
58import "../openzeppelin-contracts/contracts/token/ERC721/ERC721.sol";
59import "../openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol";
60import "../openzeppelin-contracts/contracts/math/SafeMath.sol";
61import "../openzeppelin-contracts/contracts/utils/Address.sol";
62import "../openzeppelin-contracts/contracts/utils/Counters.sol";
63import "./ERC20Token.sol";
64
65contract NFTtoken is ERC721 {
66 using SafeMath for uint256;
67 using Address for address;
68 using Counters for Counters.Counter;
69 Counters.Counter private _tokenIds;
70
71 bytes32[] candidates = [bytes32('Rama'), bytes32('Nick'), bytes32('Jose')];
72 ERC20Token ERC20TokenContract = new ERC20Token(1000, 1, candidates); //instantiating an ERC20 contract
73
74
75 address payable public owner;
76 mapping(bytes4 => bool) supportedInterfaces;
77
78 mapping(uint256 => address) tokenOwners; //a mapping from NFT ID to the address that owns it
79 mapping(address => uint256) balances; //a mapping from NFT ID to the address that owns it
80 mapping(uint256 => address) allowance; //a mapping from NFT ID to approved address
81 mapping(address => mapping(address => bool)) operators; //Mapping from owner address to mapping of operator addresses.
82 // mapping (uint256 => string) idToUri;
83 uint8 public decimals;
84
85 uint256[] public allValidTokenIds;
86 mapping(uint256 => uint256) private allValidTokenIndex;
87 string[] public allNFTNames;
88
89 struct NFT {
90 //uint NFTID;
91 string name;
92 address creator;
93 }
94
95 mapping(address => NFT) public nftInfo;
96
97
98 constructor() ERC721("NC NFT example", "NCNFT") {
99 owner = msg.sender;
100 decimals = 0;
101 }
102
103
104 function mint(string calldata nftName) external payable {
105 uint256 newItemId = _tokenIds.current();
106 _mint(msg.sender, newItemId);
107
108 nftInfo[msg.sender].name = nftName;
109 nftInfo[msg.sender].creator = msg.sender;
110
111 allValidTokenIndex[newItemId] = allValidTokenIds.length;
112 allValidTokenIds.push(newItemId);
113 _tokenIds.increment();
114 }
115
116 function transferNFT(address from, address to, uint256 tokenId) public returns (bool){
117 transferFrom(from, to, tokenId);
118 ERC20TokenContract.transferFrom(to, nftInfo[from].creator, 10);
119//<-----***********This is throwing an error! I am trying to call ERC20Token.transferFrom.
120 }
121
122 function allNFTs() public view returns (uint256[] memory) {
123 return allValidTokenIds;
124 }
125}
126
127MetaMask - RPC Error: [ethjs-query] while formatting outputs from RPC '{"value":{"code":-32603,"data":{"message":"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token","code":-32000,"data":{"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f":{"error":"revert","program_counter":7889,"return":"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000","reason":"ERC721: operator query for nonexistent token"},"stack":"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\n at Function.RuntimeError.fromResults (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\utils\\runtimeerror.js:94:13)\n at BlockchainDouble.processBlock (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\blockchain_double.js:627:24)\n at runMicrotasks (<anonymous>)\n at processTicksAndRejections (internal/process/task_queues.js:93:5)","name":"RuntimeError"}}}}'
128{code: -32603, message: `[ethjs-query] while formatting outputs from RPC '{…/task_queues.js:93:5)","name":"RuntimeError"}}}}'`}
129code: -32603
130message: "[ethjs-query] while formatting outputs from RPC '{\"value\":{\"code\":-32603,\"data\":{\"message\":\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\",\"code\":-32000,\"data\":{\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\":{\"error\":\"revert\",\"program_counter\":7889,\"return\":\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\",\"reason\":\"ERC721: operator query for nonexistent token\"},\"stack\":\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\n at Function.RuntimeError.fromResults (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\utils\\\\runtimeerror.js:94:13)\\n at BlockchainDouble.processBlock (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\blockchain_double.js:627:24)\\n at runMicrotasks (<anonymous>)\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\",\"name\":\"RuntimeError\"}}}}'"
131[[Prototype]]: Object
132localhost/:1 Uncaught (in promise)
133{code: -32603, message: `[ethjs-query] while formatting outputs from RPC '{…/task_queues.js:93:5)","name":"RuntimeError"}}}}'`, stack: '{\n "code": -32603,\n "message": "[ethjs-query] wh…gaeaoehlefnkodbefgpgknn/background-0.js:1:216902)'}
134code: -32603
135message: "[ethjs-query] while formatting outputs from RPC '{\"value\":{\"code\":-32603,\"data\":{\"message\":\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\",\"code\":-32000,\"data\":{\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\":{\"error\":\"revert\",\"program_counter\":7889,\"return\":\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\",\"reason\":\"ERC721: operator query for nonexistent token\"},\"stack\":\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\n at Function.RuntimeError.fromResults (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\utils\\\\runtimeerror.js:94:13)\\n at BlockchainDouble.processBlock (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\blockchain_double.js:627:24)\\n at runMicrotasks (<anonymous>)\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\",\"name\":\"RuntimeError\"}}}}'"
136stack: "{\n \"code\": -32603,\n \"message\": \"[ethjs-query] while formatting outputs from RPC '{\\\"value\\\":{\\\"code\\\":-32603,\\\"data\\\":{\\\"message\\\":\\\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\\",\\\"code\\\":-32000,\\\"data\\\":{\\\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\\\":{\\\"error\\\":\\\"revert\\\",\\\"program_counter\\\":7889,\\\"return\\\":\\\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\\\",\\\"reason\\\":\\\"ERC721: operator query for nonexistent token\\\"},\\\"stack\\\":\\\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\\\n at Function.RuntimeError.fromResults (C:\\\\\\\\Program Files\\\\\\\\WindowsApps\\\\\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\\\\\app\\\\\\\\resources\\\\\\\\static\\\\\\\\node\\\\\\\\node_modules\\\\\\\\ganache-core\\\\\\\\lib\\\\\\\\utils\\\\\\\\runtimeerror.js:94:13)\\\\n at BlockchainDouble.processBlock (C:\\\\\\\\Program Files\\\\\\\\WindowsApps\\\\\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\\\\\app\\\\\\\\resources\\\\\\\\static\\\\\\\\node\\\\\\\\node_modules\\\\\\\\ganache-core\\\\\\\\lib\\\\\\\\blockchain_double.js:627:24)\\\\n at runMicrotasks (<anonymous>)\\\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\\\",\\\"name\\\":\\\"RuntimeError\\\"}}}}'\",\n \"stack\": \"Error: [ethjs-query] while formatting outputs from RPC '{\\\"value\\\":{\\\"code\\\":-32603,\\\"data\\\":{\\\"message\\\":\\\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\\",\\\"code\\\":-32000,\\\"data\\\":{\\\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\\\":{\\\"error\\\":\\\"revert\\\",\\\"program_counter\\\":7889,\\\"return\\\":\\\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\\\",\\\"reason\\\":\\\"ERC721: operator query for nonexistent token\\\"},\\\"stack\\\":\\\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\\\n at Function.RuntimeError.fromResults (C:\\\\\\\\Program Files\\\\\\\\WindowsApps\\\\\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\\\\\app\\\\\\\\resources\\\\\\\\static\\\\\\\\node\\\\\\\\node_modules\\\\\\\\ganache-core\\\\\\\\lib\\\\\\\\utils\\\\\\\\runtimeerror.js:94:13)\\\\n at BlockchainDouble.processBlock (C:\\\\\\\\Program Files\\\\\\\\WindowsApps\\\\\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\\\\\app\\\\\\\\resources\\\\\\\\static\\\\\\\\node\\\\\\\\node_modules\\\\\\\\ganache-core\\\\\\\\lib\\\\\\\\blockchain_double.js:627:24)\\\\n at runMicrotasks (<anonymous>)\\\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\\\",\\\"name\\\":\\\"RuntimeError\\\"}}}}'\\n at new i (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:148782)\\n at s (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146325)\\n at Object.internal (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146935)\\n at y.<anonymous> (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:210928)\\n at Object.h (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:35204)\\n at u (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:117610)\\n at y.a.emit (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:118146)\\n at y._setTransactionStatus (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:46740)\\n at y.setTxStatusFailed (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:45972)\\n at B._failTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:225990)\\n at B.approveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:217659)\\n at async B.updateAndApproveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:216902)\"\n}\n at new i (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:148782)\n at s (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146325)\n at Object.internal (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146935)\n at y.<anonymous> (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:210928)\n at Object.h (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:35204)\n at u (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:117610)\n at y.a.emit (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:118146)\n at y._setTransactionStatus (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:46740)\n at y.setTxStatusFailed (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:45972)\n at B._failTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:225990)\n at B.approveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:217659)\n at async B.updateAndApproveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:216902)"
137[[Prototype]]: Object
138setTimeout (async)
139(anonymous) @ inpage.js:1
140write @ inpage.js:1
141// Import libraries we need.
142import { default as Web3} from 'web3';
143import { default as contract } from 'truffle-contract'
144
145import voting_artifacts from '../../build/contracts/Voting.json'
146import voting_artifacts2 from '../../build/contracts/DeedToken.json'
147
148window.App = {
149 start: function() {
150 var self = this;
151 self.transferNFT();
152 },
153transferNFT: function() {
154 NFTContract.deployed().then(function(contractInstance) {
155 let toAddress = $("#to-address").val();
156 let NFTid_temp = $("#nft-id").val();
157 let NFTid = NFTid_temp.substring(7);
158 contractInstance.transferFrom(web3.currentProvider.selectedAddress, toAddress, NFTid, {gas: 140000, from: web3.eth.accounts[0]});
159 })
160}
161}
162
163window.addEventListener('load', async function() {
164 if (window.ethereum) {
165 await window.ethereum.send('eth_requestAccounts');
166 window.web3 = new Web3(window.ethereum);
167 }
168 else {
169 console.warn("No web3 detected.");
170 window.web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:8545"));
171 }
172
173 App.start();
174});
175// Inside the nfts contract
176ERC20 token = ERC20("your token address here");
177
And then you will be able to interact with that token as:
1pragma solidity ^0.7.0;
2import "../openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
3import "../openzeppelin-contracts/contracts/math/SafeMath.sol";
4
5contract ERC20Token is IERC20 {
6 using SafeMath for uint256;
7 bytes32[] public candidateList;
8
9 uint public totalTokens;
10 uint public balanceTokens;
11 uint public tokenPrice;
12
13 // what is the voter address?
14 // total tokens purchased
15 // tokens voted per candidate
16
17 struct voter {
18 address voterAddress;
19 uint tokensBought;
20 uint256[] tokensUsedPerCandidate;
21 }
22
23 mapping(address => voter) public voterInfo;
24
25 mapping(bytes32 => uint256) public votesReceived;
26
27 string public symbol;
28 string public name;
29 uint8 public decimals;
30
31 mapping(address => uint256) balances;
32 mapping(address => mapping(address => uint256)) allowed;
33
34 constructor(uint256 _totalTokens, uint256 _tokenPrice, bytes32[] memory _candidateNames) {
35 symbol = "NCToken";
36 name = "NCSOFT TOKEN";
37 decimals = 0;
38 totalTokens = _totalTokens;
39 balanceTokens = _totalTokens;
40 tokenPrice = _tokenPrice;
41 candidateList = _candidateNames;
42 emit Transfer(address(0), msg.sender, totalTokens);
43
44
45 function transferFrom(address from, address to, uint256 tokens) public override returns (bool) { //This is the function I am trying to call from ERC721 contract
46 balances[from] = SafeMath.sub(balances[from], tokens);
47 allowed[from][msg.sender] = SafeMath.sub(allowed[from][msg.sender], tokens);
48 balances[to] = SafeMath.add(balances[to], tokens);
49 emit Transfer(from, to, tokens);
50 return true;
51 }
52
53}
54// SPDX-License-Identifier: MIT
55pragma solidity ^0.7.0;
56
57import "../openzeppelin-contracts/contracts/token/ERC721/IERC721.sol";
58import "../openzeppelin-contracts/contracts/token/ERC721/ERC721.sol";
59import "../openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol";
60import "../openzeppelin-contracts/contracts/math/SafeMath.sol";
61import "../openzeppelin-contracts/contracts/utils/Address.sol";
62import "../openzeppelin-contracts/contracts/utils/Counters.sol";
63import "./ERC20Token.sol";
64
65contract NFTtoken is ERC721 {
66 using SafeMath for uint256;
67 using Address for address;
68 using Counters for Counters.Counter;
69 Counters.Counter private _tokenIds;
70
71 bytes32[] candidates = [bytes32('Rama'), bytes32('Nick'), bytes32('Jose')];
72 ERC20Token ERC20TokenContract = new ERC20Token(1000, 1, candidates); //instantiating an ERC20 contract
73
74
75 address payable public owner;
76 mapping(bytes4 => bool) supportedInterfaces;
77
78 mapping(uint256 => address) tokenOwners; //a mapping from NFT ID to the address that owns it
79 mapping(address => uint256) balances; //a mapping from NFT ID to the address that owns it
80 mapping(uint256 => address) allowance; //a mapping from NFT ID to approved address
81 mapping(address => mapping(address => bool)) operators; //Mapping from owner address to mapping of operator addresses.
82 // mapping (uint256 => string) idToUri;
83 uint8 public decimals;
84
85 uint256[] public allValidTokenIds;
86 mapping(uint256 => uint256) private allValidTokenIndex;
87 string[] public allNFTNames;
88
89 struct NFT {
90 //uint NFTID;
91 string name;
92 address creator;
93 }
94
95 mapping(address => NFT) public nftInfo;
96
97
98 constructor() ERC721("NC NFT example", "NCNFT") {
99 owner = msg.sender;
100 decimals = 0;
101 }
102
103
104 function mint(string calldata nftName) external payable {
105 uint256 newItemId = _tokenIds.current();
106 _mint(msg.sender, newItemId);
107
108 nftInfo[msg.sender].name = nftName;
109 nftInfo[msg.sender].creator = msg.sender;
110
111 allValidTokenIndex[newItemId] = allValidTokenIds.length;
112 allValidTokenIds.push(newItemId);
113 _tokenIds.increment();
114 }
115
116 function transferNFT(address from, address to, uint256 tokenId) public returns (bool){
117 transferFrom(from, to, tokenId);
118 ERC20TokenContract.transferFrom(to, nftInfo[from].creator, 10);
119//<-----***********This is throwing an error! I am trying to call ERC20Token.transferFrom.
120 }
121
122 function allNFTs() public view returns (uint256[] memory) {
123 return allValidTokenIds;
124 }
125}
126
127MetaMask - RPC Error: [ethjs-query] while formatting outputs from RPC '{"value":{"code":-32603,"data":{"message":"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token","code":-32000,"data":{"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f":{"error":"revert","program_counter":7889,"return":"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000","reason":"ERC721: operator query for nonexistent token"},"stack":"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\n at Function.RuntimeError.fromResults (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\utils\\runtimeerror.js:94:13)\n at BlockchainDouble.processBlock (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\blockchain_double.js:627:24)\n at runMicrotasks (<anonymous>)\n at processTicksAndRejections (internal/process/task_queues.js:93:5)","name":"RuntimeError"}}}}'
128{code: -32603, message: `[ethjs-query] while formatting outputs from RPC '{…/task_queues.js:93:5)","name":"RuntimeError"}}}}'`}
129code: -32603
130message: "[ethjs-query] while formatting outputs from RPC '{\"value\":{\"code\":-32603,\"data\":{\"message\":\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\",\"code\":-32000,\"data\":{\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\":{\"error\":\"revert\",\"program_counter\":7889,\"return\":\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\",\"reason\":\"ERC721: operator query for nonexistent token\"},\"stack\":\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\n at Function.RuntimeError.fromResults (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\utils\\\\runtimeerror.js:94:13)\\n at BlockchainDouble.processBlock (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\blockchain_double.js:627:24)\\n at runMicrotasks (<anonymous>)\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\",\"name\":\"RuntimeError\"}}}}'"
131[[Prototype]]: Object
132localhost/:1 Uncaught (in promise)
133{code: -32603, message: `[ethjs-query] while formatting outputs from RPC '{…/task_queues.js:93:5)","name":"RuntimeError"}}}}'`, stack: '{\n "code": -32603,\n "message": "[ethjs-query] wh…gaeaoehlefnkodbefgpgknn/background-0.js:1:216902)'}
134code: -32603
135message: "[ethjs-query] while formatting outputs from RPC '{\"value\":{\"code\":-32603,\"data\":{\"message\":\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\",\"code\":-32000,\"data\":{\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\":{\"error\":\"revert\",\"program_counter\":7889,\"return\":\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\",\"reason\":\"ERC721: operator query for nonexistent token\"},\"stack\":\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\n at Function.RuntimeError.fromResults (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\utils\\\\runtimeerror.js:94:13)\\n at BlockchainDouble.processBlock (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\blockchain_double.js:627:24)\\n at runMicrotasks (<anonymous>)\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\",\"name\":\"RuntimeError\"}}}}'"
136stack: "{\n \"code\": -32603,\n \"message\": \"[ethjs-query] while formatting outputs from RPC '{\\\"value\\\":{\\\"code\\\":-32603,\\\"data\\\":{\\\"message\\\":\\\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\\",\\\"code\\\":-32000,\\\"data\\\":{\\\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\\\":{\\\"error\\\":\\\"revert\\\",\\\"program_counter\\\":7889,\\\"return\\\":\\\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\\\",\\\"reason\\\":\\\"ERC721: operator query for nonexistent token\\\"},\\\"stack\\\":\\\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\\\n at Function.RuntimeError.fromResults (C:\\\\\\\\Program Files\\\\\\\\WindowsApps\\\\\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\\\\\app\\\\\\\\resources\\\\\\\\static\\\\\\\\node\\\\\\\\node_modules\\\\\\\\ganache-core\\\\\\\\lib\\\\\\\\utils\\\\\\\\runtimeerror.js:94:13)\\\\n at BlockchainDouble.processBlock (C:\\\\\\\\Program Files\\\\\\\\WindowsApps\\\\\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\\\\\app\\\\\\\\resources\\\\\\\\static\\\\\\\\node\\\\\\\\node_modules\\\\\\\\ganache-core\\\\\\\\lib\\\\\\\\blockchain_double.js:627:24)\\\\n at runMicrotasks (<anonymous>)\\\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\\\",\\\"name\\\":\\\"RuntimeError\\\"}}}}'\",\n \"stack\": \"Error: [ethjs-query] while formatting outputs from RPC '{\\\"value\\\":{\\\"code\\\":-32603,\\\"data\\\":{\\\"message\\\":\\\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\\",\\\"code\\\":-32000,\\\"data\\\":{\\\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\\\":{\\\"error\\\":\\\"revert\\\",\\\"program_counter\\\":7889,\\\"return\\\":\\\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\\\",\\\"reason\\\":\\\"ERC721: operator query for nonexistent token\\\"},\\\"stack\\\":\\\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\\\n at Function.RuntimeError.fromResults (C:\\\\\\\\Program Files\\\\\\\\WindowsApps\\\\\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\\\\\app\\\\\\\\resources\\\\\\\\static\\\\\\\\node\\\\\\\\node_modules\\\\\\\\ganache-core\\\\\\\\lib\\\\\\\\utils\\\\\\\\runtimeerror.js:94:13)\\\\n at BlockchainDouble.processBlock (C:\\\\\\\\Program Files\\\\\\\\WindowsApps\\\\\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\\\\\app\\\\\\\\resources\\\\\\\\static\\\\\\\\node\\\\\\\\node_modules\\\\\\\\ganache-core\\\\\\\\lib\\\\\\\\blockchain_double.js:627:24)\\\\n at runMicrotasks (<anonymous>)\\\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\\\",\\\"name\\\":\\\"RuntimeError\\\"}}}}'\\n at new i (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:148782)\\n at s (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146325)\\n at Object.internal (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146935)\\n at y.<anonymous> (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:210928)\\n at Object.h (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:35204)\\n at u (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:117610)\\n at y.a.emit (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:118146)\\n at y._setTransactionStatus (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:46740)\\n at y.setTxStatusFailed (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:45972)\\n at B._failTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:225990)\\n at B.approveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:217659)\\n at async B.updateAndApproveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:216902)\"\n}\n at new i (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:148782)\n at s (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146325)\n at Object.internal (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146935)\n at y.<anonymous> (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:210928)\n at Object.h (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:35204)\n at u (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:117610)\n at y.a.emit (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:118146)\n at y._setTransactionStatus (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:46740)\n at y.setTxStatusFailed (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:45972)\n at B._failTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:225990)\n at B.approveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:217659)\n at async B.updateAndApproveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:216902)"
137[[Prototype]]: Object
138setTimeout (async)
139(anonymous) @ inpage.js:1
140write @ inpage.js:1
141// Import libraries we need.
142import { default as Web3} from 'web3';
143import { default as contract } from 'truffle-contract'
144
145import voting_artifacts from '../../build/contracts/Voting.json'
146import voting_artifacts2 from '../../build/contracts/DeedToken.json'
147
148window.App = {
149 start: function() {
150 var self = this;
151 self.transferNFT();
152 },
153transferNFT: function() {
154 NFTContract.deployed().then(function(contractInstance) {
155 let toAddress = $("#to-address").val();
156 let NFTid_temp = $("#nft-id").val();
157 let NFTid = NFTid_temp.substring(7);
158 contractInstance.transferFrom(web3.currentProvider.selectedAddress, toAddress, NFTid, {gas: 140000, from: web3.eth.accounts[0]});
159 })
160}
161}
162
163window.addEventListener('load', async function() {
164 if (window.ethereum) {
165 await window.ethereum.send('eth_requestAccounts');
166 window.web3 = new Web3(window.ethereum);
167 }
168 else {
169 console.warn("No web3 detected.");
170 window.web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:8545"));
171 }
172
173 App.start();
174});
175// Inside the nfts contract
176ERC20 token = ERC20("your token address here");
177token.transferFrom("args");
178
Hope you find this information useful :)
Community Discussions contain sources that include Stack Exchange Network
Tutorials and Learning Resources in Ethereum
Tutorials and Learning Resources are not available at this moment for Ethereum