how to get error message from contract modifier in UI? - ethereum

When testing a contract on Remix I notice if a method does not pass a modifier you actually see the error message shown in the window below the contract code. Is this something I can get from web3, or how can I in my own UI get this error messages from the contract when provided?
Here is a simple contract:
address public owner;
modifier onlyOwner() {
require(msg.sender == owner, "Owner account is required");
_;
}
constructor() public {
owner = msg.sender;
}
function doStuff()
external
view
onlyOwner
returns (bool) {
return true;
}
When I call the contract not from owner in remix, in the console I get this message:
call to Contract.doStuff errored: VM error: revert.
revert The transaction has been reverted to the initial state.
Reason provided by the contract: "Owner account is required". Debug the transaction to get more information.
Is the error it gives something I can get from a web3 transaction? I do not see it

Related

unable to withdraw from the contract

I have a very simple contract, and it works on remix. I'm able to deposit (fallback) and withdraw.
I want to do it on my webapp with web3js library.
the contract has these functions
fallback() external payable {}
modifier onlyOwner(address caller) {
require(caller == _owner, "You are not the owner of the contract");
_;
}
function getContractAmount(address caller) public view onlyOwner(caller) returns (uint256){
return address(this).balance;
}
function withdraw() external {
address payable to = payable(msg.sender);
to.transfer(getContractAmount(to));
}
on my webapp I'm able to interact with the other function of my contract, so I imported address contract and ABI as well.
I have this function
contract.methods.withdraw().call().then((res) => {
console.dir(res)
$('#info').html(res);
})
.catch(revertReason => {
console.log({ revertReason });
$('#info').text(revertReason);
}
)
But I'm not able to retrieve the amount of my smart contract (yes the smart contract has ether)
with console.dir, I get "u"
The call() method is for read-only calls.
Since the withdraw() function changes the state, you need to send() a transaction.
contract.methods.withdraw().send({
from: senderAddress
})
Your web3 instance or the node needs to know the private key to the senderAddress Use wallet.add() to add the private key to the web3 instance.

Smart Contract withdraw function does not work and i get an error

the withdraw function gets me an error and it shows send and transfer are only available for object of type address payable and not address...
Confusing!!
solidity
//SPDX-License-Identifier: MIT
//this line of code was created to fund account
//show the value of fund in the address
pragma solidity ^0.8.0;
// the fundMe contract should be able to accept payment
function withdraw()payable public {
msg.sender.transfer(address(this).balance);
}
}
In Solidity, there is a difference between a normal address and a payable address so the correct way to send Ether to the sender would be payable(msg.sender).transfer(address(this).balance); this converts the normal address to a payable address. For more details take a look at this
I think up until solidity ^0.8.0, msg.sender was payable. withdraw function should be called only by the owner of the contract and you do not need to make it payable.
address payable private owner;
// set the owner when the contract is created
constructor(){
owner=payable(msg.sender)
}
function withdraw() public {
require(msg.sender==owner,"only contract owner can call this");
owner.transfer(address(this).balance);
}
However, using transfer is not safe. Because .transfer() sends more gas than 2300. Thus making it possible for reentrancy. A better way would be:
function withdraw() public {
require(msg.sender==owner,"only contract owner can call this");
(bool success, ) = owner.call{value:address(this).balance}("");
// success should be true
require(success,"Withdraw failed")
}

What is the difference between msg.sender and address(this)?

What is the difference between msg.sender and address(this) in the below code?
**pragma solidity ^0.8.0;
contract Escrow{
address public payer;
address payable public payee;
address public lawyer;
uint public amount;
constructor(
address _payer,
address payable _payee,
uint _amount) {
payer = _payer;
payee = _payee;
lawyer = msg.sender;
amount = _amount;
}
function deposit() payable public {
require(msg.sender == payer, 'Sender must be the payer');
require(address(this).balance <= amount, 'Cant send more than escrow amount');
}
function release() public {
require(address(this).balance == amount, 'cannot release funds before full amount is sent');
require(msg.sender == lawyer, 'only lawyer can release funds');
payee.transfer(amount);
}
function balanceOf() view public returns(uint) {
return address(this).balance;
}
}**
msg.sender is the address of the contract caller.
address(this) is the address of the smart contract itself.
They are both addresses in Solidity, but there is a big difference between msg.sender and address(this).
Allow me to use a simplified Smart Contract below to highlight the difference. All screenshots are from the Remix-Ethereum IDE (click here).
pragma solidity ^0.8.0;
contract Escrow {
address public owner;
constructor() {
owner = msg.sender;
}
function depositNothing() public view {
require(msg.sender == owner, 'You are not the owner!');
}
function balanceOf() view public returns(uint) {
return address(this).balance;
}
}
msg.sender
We are talking about the ACCOUNT address from which the function in the Smart Contract was called. For example, suppose in the Remix Ethereum (IDE), the Escrow Smart Contract was deployed from the ACCOUNT address:
0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
In that case, the State Variable owner will have the same address mentioned above. This is because the constructor function was called from that address.
Now, suppose we change the ACCOUNT address to:
0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2
We then call the function depositNothing from the Smart Contract which was deployed earlier. You will get the following error, however:
This is because the msg.sender in the depositNothing function equates to the second ACCOUNT address. This obviously does not equate to the first ACCOUNT Address - owner. The second argument in the require function was therefore returned along with the error.
address(this)
This is not the same as the ACCOUNT Address discussed earlier. This strictly refers to the address given to the Smart Contract when it is deployed to the Ethereum blockchain.
This can be found here:
0xd8b934580fcE35a11B58C6D73aDeE468a2833fa8

How to call a method from a contract that was instantiated from another contract via truffle console?

I'm trying to call a method from a contract that was instantiated from another contract. I use truffle console.
Here are the details: (I think you can gloss over the code, since this question is aimed at using truffle console, not fixing any bugs)
I have a contract called MyCoinSupply.sol:
pragma solidity ^0.8.0;
import "./MyCoin.sol";
contract MyCoinSupply is MyCoin("MyCoin", "MYC") // MyCoin is ERC20
{
constructor() public // gives 1000 tokens to the owner
{
_mint(msg.sender, 1000);
}
function getCoinbase() public returns (address) // for debugging purposes
{
return block.coinbase;
}
function _mintMinerReward() internal // gives 20 tokens to the miner
{
// _mint(block.coinbase, 20); // for some reason, block.coinbase is address 0
}
function _transfer(address from, address to, uint256 value) override internal
{
_mintMinerReward();
super._transfer(from, to, value);
}
}
I instantiate MyCoinSupply.sol within MyCoinDEX.sol:
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./MyCoinSupply.sol";
contract MyCoinDEX
{
IERC20 public token;
event Bought(uint256 amount);
event Sold(uint256 amount);
constructor() public
{
token = new MyCoinSupply();
}
function showSender() public view returns (address) // for debugging purposes
{
return (msg.sender);
}
function buy(uint256 amountTobuy) payable public // send ether and get tokens in exchange; 1 token == 1 ether
{
uint256 dexBalance = token.balanceOf(address(this));
require(amountTobuy > 0, "You need to send some ether");
require(amountTobuy <= dexBalance, "Not enough tokens in the reserve");
token.transfer(msg.sender, amountTobuy);
emit Bought(amountTobuy);
}
function sell(uint256 amount) public // send tokens to get ether back
{
require(amount > 0, "You need to sell at least some tokens");
uint256 allowance = token.allowance(msg.sender, address(this));
require(allowance >= amount, "Check the token allowance");
token.transferFrom(msg.sender, address(this), amount);
payable(msg.sender).transfer(amount);
emit Sold(amount);
}
}
Here's my migration for deploying contracts:
const MyCoinSupply = artifacts.require("MyCoinSupply");
const MyCoinDEX = artifacts.require("MyCoinDEX");
module.exports = function(deployer) {
deployer.deploy(MyCoinSupply);
deployer.deploy(MyCoinDEX);
};
Here's my problem:
When I try to call functions that belong to MyCoinDEX, all works well:
truffle(development)> let instance = await MyCoinDEX.deployed()
undefined
truffle(development)> instance.buy(1)
All is good here.
However, when I try the following I get an error:
truffle(development)> instance.token.balanceOf("0xE1994C1054f9c4171B8ae9a7E7a68F404c2bF829")
evalmachine.<anonymous>:0
instance.token.balanceOf("0xE1994C1054f9c4171B8ae9a7E7a68F404c2bF829")
^
Uncaught TypeError: instance.token.balanceOf is not a function
I Googled this error (I read this solution and this solution), but I didn't really stumble upon a solution. Can someone tell me how can I call token's methods from MyCoinDEX?
Thank you in advance!

solidity error with addr.transfer(1 ether)

Error message:
transact to Payment.deposit errored: VM error: revert.
revert The transaction has been reverted to the initial state.
Note: The called function should be payable if you send value and the value you send should be less than your current balance. Debug the transaction to get more information.
contract Payment{
address Account2;
address Owner;
constructor() public{
Account2 = 0x583031D1113aD414F02576BD6afaBfb302140225;
Owner = msg.sender;
}
function deposit() payable public{
address(uint160(Account2)).transfer(1 ether);
}
If you don't want to use msg.value then it is compulsory that your contract should have enough balance.
So you can create a fallback function in order to deposit enough ether to your contract first and then you can call your deposit() function.
Your contract after adding fallback function
pragma solidity ^0.5.1;
contract Payment{
address Account2;
address Owner;
constructor() public{
Account2 = 0x583031D1113aD414F02576BD6afaBfb302140225;
Owner = msg.sender;
}
function () payable external{}
function deposit() payable public{
address(uint160(Account2)).transfer(1 ether);
}
function getContractBalance() public view returns(uint) {
return address(this).balance;
}
}
It works without error on my remix VM.
So make sure:
The contract has a balance greater than 1 ether
If Account2 is a contract's address, then it need to have a fallback function to receive ether