I am wrote a contract in using Solidity for a real estate transaction. It will allow you to sale a house. I am currently testing the contract using Truffle and during my test i keep getting a error that says "Reference Error: Home Sale is not defined".
Here is the smart contract:
pragma solidity ^0.6.0;
contract HouseSale {
address payable _BuyerAddress;
address payable _Seller;
address payable _Agent;
struct Home{
uint _priceinBUSD;
address _owner;
bool _homeforsale;
}
Home[1] HomeDB;
modifier SellerOnly() {
require [msg.sender == _Seller];
_;
}
// set price of house
function setPriceofHouse(uint8 _home, uint256 _priceinBUSD) SellerOnly public {
HomeDB[_home].priceinBUSD;
}
function getPriceofHouse(uint8 _home, uint256 _priceinBUSD) public payable returns(uint256) {
return HomeDB[_home].priceinBUSD;
}
// buyer purchase home
function buyAHome(uint8 _home) public payable returns(uint256) {
buyerAddress = msg.sender;
//correct home price
if (msg.value % HomeDB[_home].priceinBUSD == 0 ++) msg.value > 0 ++ HomeDB)
(_home) {
uint256 FinalSalePrice = msg.value/HomeDB(_home).priceinBUSD;
_SellerAddress.transfer(msg.value);
_AgentAddress.transfer(msg.value/100);
return finalSalePrice;
}
}
}
And here is the test file
const HomeSaleTest = artifacts.require("HomeSale");
/*
* uncomment accounts to access the test accounts made available by the
* Ethereum client
* See docs: https://www.trufflesuite.com/docs/truffle/testing/writing-tests-in-javascript
*/
contract("HomeSale", function (accounts) {
let instance;
beforeEach('should setup the contract instance', async () => {
instance = await HomeSale.deployed();
});
it("should return the list of accounts", async ()=> {
console.log(accounts);
});
it("should return price", async () => {
const value = await instance.getPriceofHouse();
assert.equal(value, '10000')
});
});
I am pretty new to the test realm of Smart Contract development.
You're defining HomeSaleTest, but trying to deploy HomeSale.
const HomeSaleTest = artifacts.require("HomeSale");
// ^^ here
instance = await HomeSale.deployed();
// ^^ here
Solution: Rename either of the expressions so that they have the same name. For example:
const HomeSale = artifacts.require("HomeSale");
// ^^ here
instance = await HomeSale.deployed();
// ^^ here
Related
The Open Zeppelin ERC20 contract has a name(), symbol, and totalSupply() function. This is my smart contract that inherits the ERC20 contract
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
import "#openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
contract QUAD_EK is ERC20, ERC20Burnable {
constructor(address[] memory wallets, uint256[] memory amounts) ERC20("Quadency Token", "QUAD") {
require(wallets.length == amounts.length, "QUAD: wallets and amounts mismatch");
for (uint256 i = 0; i < wallets.length; i++){
_mint(wallets[i], amounts[i]);
if(i == 10){
break;
}
}
}
I've tested that the name() function works in Truffle.
describe('quad ek methods', async () => {
it('gets token name', async () => {
let quadEK = await QUAD_EK.new([account_0, account_1, account_2, account_3, account_4], amounts);
let quadName = await quadEK.name();
assert.equal(quadName.toString(), 'Quadency Token')
})
})
But when I tried to call the name() method in web3, I get the following error: TypeError: quad_ek.methods.name is not a function
My code below (the contract is loaded correctly):
module.exports = async function(callback) {
try{
const web3 = new Web3(new Web3.providers.HttpProvider(
`process.env.INFURA)`
)
);
const signInfo = web3.eth.accounts.privateKeyToAccount('process.env.QUAD_TEST0')
console.log("signingInfo", signInfo)
const nonce = await web3.eth.getTransactionCount(signInfo.address)
console.log("nonce", nonce)
const quad_ek = new web3.eth.Contract(token_abi, token_address )
**
quad_ek.methods.name().call({from: '0x72707D86053cb767A710957a6b9D8b56Dd7Fd835'}, function(error, result){
});**
}
catch(error){
console.log(error)
}
callback()
}
I'm using the documentation from web3:
myContract.methods.myMethod(123).call({from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'}, function(error, result){
...
});
My token abi does have the name function:
"name()": {
"details": "Returns the name of the token."
},
"symbol()": {
"details": "Returns the symbol of the token, usually a shorter version of the name."
},
"totalSupply()": {
"details": "See {IERC20-totalSupply}."
},
"transfer(address,uint256)": {
"details": "See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`."
},
"transferFrom(address,address,uint256)": {
"details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`."
}
In your post, you used the the full JSON file (or just its devDocs section, can't tell from the context) as the value of token_abi. This whole file is an output from the compilation process, it contains the ABI as well as other data produced by the compilator (bytecode, list of warnings, ...).
You need to pass just the abi section to new web3.eth.Contract();
const compileOutput = JSON.parse(fs.readFileSync("./QUAD_EK.JSON"));
const token_abi = compileOutput[0].abi;
const quad_ek = new web3.eth.Contract(token_abi, token_address);
I deployed the following smart contract on Ropsten ethereum test network and afterwards I tried making a transaction using #alch/alchemy-web3 npm package (Yes, I am using Alchemy API) but as you can see I got a fee on the transaction. Why is that? Aren't public view function calls supposed to cost 0 gas?
deployed smart contract
// SPDX-Lincense-Identifier: MIT
pragma solidity ^0.8.11;
contract VendingMachine {
address public owner;
mapping(address => uint256) public donutBalances;
constructor() {
owner = msg.sender;
donutBalances[address(this)] = 100;
}
function getVendingMachineBalance() public view returns (uint256) {
return donutBalances[address(this)];
}
function restock(uint amount) public {
require(msg.sender == owner, "Only the owner can restock this machine.");
donutBalances[address(this)] += amount;
}
function purchase(uint amount) public payable {
require(msg.sender == owner, "Only the owner can restock this machine.");
require(donutBalances[address(this)] >= amount, "Not enough donuts in stock to fulfill purchase request.");
require(msg.value >= amount*2 ether, "You must pay at least 2 ether / donut.");
donutBalances[address(this)] -= amount;
donutBalances[msg.sender] += amount;
}
}
transaction code javascript
const { API_URL, METAMASK_ACCOUNT_PRIVATE_KEY, METAMASK_ACCOUNT_PUBLIC_KEY } = process.env;
const { createAlchemyWeb3 } = require("#alch/alchemy-web3");
const web3 = createAlchemyWeb3(`${API_URL}`);
const contractAddress = '0xc7E286A86e4c5b8F7d52fA3F4Fe7D9DE6601b6F9'
const contractAPI = new web3.eth.Contract(contract.abi, contractAddress)
const nonce = await web3.eth.getTransactionCount(METAMASK_ACCOUNT_PUBLIC_KEY, 'latest');
const transaction = {
to: contractAddress, // faucet address to return eth
gas: 500000,
nonce: nonce,
data: contractAPI.methods.getVendingMachineBalance().encodeABI()
// optional data field to send message or execute smart contract
};
const signedTx = await web3.eth.accounts.signTransaction(transaction, METAMASK_ACCOUNT_PRIVATE_KEY)
web3.eth.sendSignedTransaction(signedTx.rawTransaction, function (error, hash) {
if (!error) {
console.log("🎉 The hash of your transaction is: ", hash, "\n Check Alchemy's Mempool to view the status of your transaction!");
} else {
console.log("❗Something went wrong while submitting your transaction:", error)
}
});
Transaction: https://ropsten.etherscan.io/tx/0x8ce3a288072809a804adac2206dc566dfb3eb3ddba3330bcb52ca6be71963b71
There are two ways to interact with a smart contract. A transaction (read-write, costs gas fees) and a call (read-only, gas free).
Your JS snippet sends a transaction. If you want to invoke the getVendingMachineBalance() function using a (gas free) call, you can use the .call() web3js method.
const contractAPI = new web3.eth.Contract(contract.abi, contractAddress);
const response = await contractAPI.methods.getVendingMachineBalance().call();
I'm trying to follow along with one of the solidity tutorials on youtube. And I'm getting stuck at this particular moment.
This is a solidity code:
pragma solidity ^0.5.0;
import "./Token.sol";
contract EthSwap {
string public name = "EthSwap Instant Exchange";
Token public token;
constructor(Token _token) public {
token = _token;
}
}
Here is a deployment code:
const Token = artifacts.require("Token");
const EthSwap = artifacts.require("EthSwap");
module.exports = async function(deployer) {
// Deploy Token
await deployer.deploy(Token);
const token = await Token.deployed()
// Deploy EthSwap
await deployer.deploy(EthSwap, token.address);
const ethSwap = await EthSwap.deployed()
// Transfer all tokens to EthSwap (1 million)
await token.transfer(ethSwap.address, '1000000000000000000000000')
};
And this is a code for automated test:
const Token = artifacts.require("Token");
const EthSwap = artifacts.require("EthSwap");
require('chai')
.use(require('chai-as-promised'))
.should()
function tokens(n) {
return web3.utils.toWei(n, 'ether');
}
contract('EthSwap', (accounts) => {
let token, ethSwap
before(async () => {
token = await Token.new()
ethSwap = await EthSwap.new(token.address)
// Transfer all tokens to EthSwap (1 million)
await token.transfer(ethSwap.address, tokens('1000000'))
})
describe('Token deployment', async () => {
it('contract has a name', async () => {
let token = await Token.new()
const name = await token.name()
assert.equal(name, 'DApp Token')
})
})
describe('EthSwap deployment', async () => {
it('contract has a name', async () => {
let ethSwap = await EthSwap.new()
const name = await ethSwap.name()
assert.equal(name, 'EthSwap Instant Exchange')
})
it('contract has tokens', async () => {
let balance = await token.balanceOf(ethSwap.address)
assert.equal(balance.toString(), tokens('1000000'))
})
})
})
The test runed normally before I added this code to the solidity code:
constructor(Token _token) public {
token = _token;
}
Now I get the following in my terminal:
2 passing (559ms)
1 failing
Contract: EthSwap
EthSwap deployment
contract has a name:
Invalid number of parameters for "undefined". Got 0 expected 1!
Error
at PromiEvent (C:\Users\user\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\contract\lib\promievent.js:9:1)
at C:\Users\user\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\contract\lib\execute.js:223:1
at Function.new (C:\Users\user\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\contract\lib\contract\constructorMethods.js:57:1)
at _callee4$ (C:/Users/user/eth_swap/test/EthSwap.test.js:32:24)
at tryCatch (node_modules#babel\runtime\node_modules\regenerator-runtime\runtime.js:45:40)
at Generator.invoke [as _invoke] (node_modules#babel\runtime\node_modules\regenerator-runtime\runtime.js:271:22)
at Generator.prototype. [as next] (node_modules#babel\runtime\node_modules\regenerator-runtime\runtime.js:97:21)
at step (test\EthSwap.test.js:3:191)
at C:\Users\user\eth_swap\test\EthSwap.test.js:3:437
at new Promise ()
at Context. (test\EthSwap.test.js:3:99)
at processImmediate (node:internal/timers:466:21)
Can someone explane what might be the problem. It seems that I did everything exactly as done in the tutorial.
Your contract has constructor function set. constructor function means when you initalize an instance, you have to pass arguments that used in constructor(Token _token). this argument probably is the "address". So in your deployment function
await deployer.deploy(Token);
you have to pass the token as the second argument
await deployer.deploy(Token,tokenAddress);
if you needed more arguments, you would just pass them in order. first argument is the contract, then arguments in constructor, and the last argument is the options object if needed
I am working on a simple real estate smart contract in Solidity and I keep receiving this error during testing in Truffle. " TypeError: No matching declaration found after variable lookup". The goal is to have the seller be the one to set the price of the house only.
Here is the contract code for your reference.
pragma solidity ^0.5.16;
contract HomeSale {
address payable _buyerAddress;
address payable _seller;
address payable _agent;
struct Home{
uint _priceinBUSD;
address _owner;
bool _homeforsale;
}
Home[1] HomeDB;
modifier onlySeller() {
require [msg.sender == _seller];
_;
}
// set price of house
function price(uint8 _home, uint256 _priceinBUSD) onlySeller public returns (uint64){
require(msg.sender);
HomeDB[_home].priceinBUSD;
}
function getPriceofHouse(uint8 _home, uint256 _priceinBUSD) public payable returns(uint256) {
return HomeDB[_home].priceinBUSD;
}
// buyer purchase home
function buyAHome(uint8 _home) public payable returns(uint256) {
_buyerAddress = msg.sender;
//correct home price
if (msg.value ==HomeDB[_home].priceinBUSD)(_home);
uint256 finalSalePrice = msg.value/HomeDB(_home).priceinBUSD;
_seller.transfer(msg.value);
_agent.transfer(msg.value/100);
return finalSalePrice;
}
}
Here is my test file:
const HomeSaleTest = artifacts.require("HomeSale");
/*
* uncomment accounts to access the test accounts made available by the
* Ethereum client
* See docs: https://www.trufflesuite.com/docs/truffle/testing/writing-tests-in-javascript
*/
contract("HomeSale", function (accounts) {
let instance;
beforeEach('should setup the contract instance', async () => {
instance = await HomeSale.deployed();
});
it("should return the list of accounts", async ()=> {
console.log(accounts);
});
it("should return price", async () => {
const value = await instance.getPriceofHouse();
assert.equal(value, '10000')
});
});
I am creating a contract (Exchange) within the Factory contract and I want to access via Web3 the Factory contract.
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
import "./Exchange.sol";
contract Factory {
mapping(address => address) public tokenToExchange;
function createExchange(address _tokenAddress) public returns (address) {
require(_tokenAddress != address(0), "invalid token address");
require(
tokenToExchange[_tokenAddress] == address(0),
"exchange already exists"
);
Exchange exchange = new Exchange(_tokenAddress);
tokenToExchange[_tokenAddress] = address(exchange);
return address(exchange);
}
function getExchange(address _tokenAddress) public view returns (address) {
return tokenToExchange[_tokenAddress];
}
}
For example, I want to addLiquidity and for that I need access to Exchange contract. But before I want to check via getExchange() function within Factory contract if the Exchange() contract is already created.
addLiquidity = async (tokenAmount: string, ethAmount: string) => {
this.setState({ loading: true });
let exchangeAddress: string;
try {
const factory = this.state.factory;
const tokenAddress = this.state.tokenAddress;
// if Exchange not already created then we will get of address(0)
0x0000000000000000000000000000000000000000
exchangeAddress = await factory.methods.getExchange(tokenAddress).call();
if (exchangeAddress.startWith('0x00') {
//Exchange address
exchangeAddress = await factory.methods
.createExchange(this.state.tokenAddress)
.call();
console.log(`Èxchange created at: ${exchangeAddress}`);
}
console.log('address already created')
} catch (err) {
console.log(err);
this.setState({ loading: false });
return;
}
If I run the function getExchange(tokenAddress) is alway return the address of address(0) 0x0000000000000000000000000000000000000000
If the return value is 0x0000000000000000000000000000000000000000 the token does not yet have an exchange.
I think that is expected.
https://docs.uniswap.org/protocol/V1/guides/connect-to-uniswap#get-exchange-address