Revert throws "missing revert data" in inherited method - ethereum

I've got a base contract which I use to add functionality to other contracts by inheritance.
For some reason, neither revert nor require are working as expected when the method is called by a descendent which acquires the method via "is". eg contract Sample is AttribChecker
Here's part of the method in Attribchecker;
function getAttribute(string memory attribName) public virtual view returns(string memory) {
BindingCollection coll = BindingCollection(_bindingCollectionAddr);
bool attrExists = coll.existsAttrib(attribName);
console.log("attr exists?", attrExists); //works as expected
if (!attrExists) revert("no such attrib"); //when attrExists is true, fails here
[...]
}
Instead of getting a normal revert message, I get this error:
Error: missing revert data in call exception [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ] (error={"stackTrace":[{"type":4,"sourceReference":{"function":"getAttribute","contract":"SampleContract","sourceName":"contracts/Embeddable.sol","sourceContent":"//SPDX-License-Identifier: Unlicense\npragma solidity ^0.8.0;\n\nimport \"./BKLibrary.sol\";\nimport \"./BindingCollection.sol\";\nimport \"hardhat/console.sol\";\n\ncontract Embeddable {\n using BKLibrary for string;\n \n bool private _published;\n string private _fqBinding;\n address private _bindingCollectionAddr;\n address private owner;\n\n modifier onlyOwner {\n require(msg.sender==owner, \"onlyOwner\");\n _;\n }\n\n constructor(address bindingColAddress_) (more...)
I would like it to fail with the normal revert message so I can see that it failed because of "no such attrib" not all this other stuff.
Why is it failing with "missing revert data" on the call to revert?

require takes a boolean, like so:
require(condition, error message);
So your check should look like this:
require(attrExists, "no such attrib");
But your problem is probably with the coll.existsAttrib. From the stack trace, it appears that the revert is caused by an external call. The only external call here is the coll.existsAttrib.

Related

Warning: Function state mutability can be restricted to pure function

I am new to solidity and I have been trying to print out simple messages using functions in solidity, but I have failed to deploy successfully, and there is an error that I can not figure out what's wrong.
This is what I have tried so far:
pragma solidity ^0.6.0;
contract test {
string public _feedback;
function reply(string memory feedback) public
{
feedback = "Well done!";
}
}
The error I am receiving is "Warning: Function state mutability can be restricted to pure function"
The compiler simply WARNS that the result of the execution of the function reply is fixed and "canonically" this can be indicated by adding a pure specifier to it:
function reply(string memory feedback) public pure
{
feedback = "Well done!";
}
But even without this change, the contract will be compiled and created correctly. Only in its current form, you will not be able to understand in any way what it is working out :-)

Solidity Internal exception in StandardCompiler

This is the source code
pragma solidity ^0.5.1;
contract myContract{
string value;
constructor() public {
value = "myValue";
}
function get() public view returns(string memory){
return value;
}
function set(string memory _value) public{
value = _value;
}
}
Selected Compiler on Remix IDE is 0.5.1+commit.c8a2cb62
Selected Environment is Javascript VM
When I compile the command I get this error
Internal exception in StandardCompiler::compileInternal: /root/project/libevmasm/ExpressionClasses.cpp(187): Throw in function ExpressionClasses::Id dev::eth::ExpressionClasses::tryToSimplify(const dev::eth::ExpressionClasses::Expression &)
Dynamic exception type: boost::exception_detail::clone_impl<dev::eth::OptimizerException>
std::exception::what: Rule list not properly initialized.
[dev::tag_comment*] = Rule list not properly initial
However this error does not pop up for same source code if I select the compiler as 0.5.11
Other users are saying that they are getting this error on pre 0.5.3 compilers.
This is a bug in a certain version of the compiler - it does not work properly if the javascript runtime environment does not provide enough stack space or memory. It should work with the most recent compilers.
Check this thread for more info

Solidity error message when executing smart contract: "the constructor should be payable if you send value"

I am trying to learn solidity through coding the smart contract below (see snippet below) .
I have been able to successfully compile (i.e. without bugs) the smart contract, the object of which is to payout an inheritance from one ethereum wallet address to another (e.g. a family member).
I have also been able to deploy it but I get the following error message (also see attached pic) when i try to transfer an inheritance to a payee.
Any help is greatly appreciated !
error message:
"transact to Will.setInheritance errored: VM error: revert.
revert The transaction has been reverted to the initial state.
Note: The constructor should be payable if you send value. Debug the transaction to get more information"
pragma solidity ^0.5.1;
//Use a double forward slash to write a like this one
// Line1 : First we nominate which version of the SOLIDITY code we are using.
//This is always the first step in our code.
// Here we tell REMIX that the the source code we are using is version 0.5.1 or above (by using the ^ - carrot symbol)
// We will start building our SC which will eventually split the inheritance of a persons will (e.g. Grandfather) amongst the Family members
contract Will {
//Line 9 : Each new contract must be named as “contract”, then the name with the first letter always CAPITALIZED, followed by open/close curly brackets to contain the logic.
address owner;
uint fortune;
bool isDeceased;
// Line 13: here we declare the variables of the smart contract - each variable must be listed along with its variable type in SOLIDITY
// Line 13: owner is of the address type of variable in SOLIDITY (unique variable in SOLIDITY - refers to an ethereum network address)
// Line 14: fortune is of the type uint (unsigned integer = a positive only integer)
// Line 15: isDeceased is a boolean variable (i.e. TRUE or FALSE type)
constructor() public payable {
owner = msg.sender;
fortune = msg.value;
isDeceased = false;
}
// Line 22: here we use a constructor function to set these values in he contract
// The “public” keyword is what’s known as a “visibility modifier” which tells the contract who is allowed to call the function.
// Public means that the function can be called within the contract and outside of it by someone else or another contract.
// The “payable” keyword allows the function to send and receive ether.
// When we deploy the contract we can initialize it with an ether balance.
// When the contract receives ether, it will store it in its own address.
// Then we will use the SC to transfer the ether to another adress (or inheritor)
// Line 23: we set the owner to “msg.sender”, which is a built-in global variable representative of the address that is calling the function.
//In this case, it will be the owner of the funds.
// Line 24: The fortune is set to “msg.value”, which is another built-in variable that tells us how much ether has been sent.
// Line 25: We set the isDeceased to false
modifier onlyOwner {
require (msg.sender ==owner);
_;
}
modifier mustBeDeceased {
require (isDeceased == true);
_;
}
// Modifiers are add-ons to functions that contain conditional logic.
// Line 41 declares “onlyOwner” modifier.
// If added to a function, it can only be called if the caller (msg.sender) is equivalent to the owner variable as stated above (remember how we set the owner in the constructor). We will need this to allow the distribution of funds, which will be implemented later.
// The “require” keyword states that we want isDeceased to be true otherwise solidity will throw an error and the execution will stop.
// The “_;” at the end tells the execution to shift to the actual function after it’s done reading the modifier.
// Now we must declare how the inheritance is divided amongst the family members.
// We will need their public wallet keys (addresses) and their desired allotments.
// First we create a list to store the wallet addresses (of the family members)
// And we create a and a function that sets the inheritance for each address.
address payable[] wallets;
//ABOVE WE HAVE TO ENTER payable to tell SOLIDITY that the address for the payout of the money is the wallet address
// function will not work without adding "address" here
mapping (address => uint) inheritance;
function setInheritance(address payable _wallet, uint _inheritance) public onlyOwner {
wallets.push(_wallet);
inheritance [_wallet] = _inheritance;
}
// Line 67: declares an empty array called “wallets” for storing the family members’ wallet addresses.
// This is a list-like data structure . The square brackets after “address” indicate it’s an array of items rather than a single variable.
// Line 69: Creates a mapping from an address type to a uint type named “inheritance”
// We will use this for distributing the inheritance to a family members wallet (It’s the equivalent of a “dictionary” in other languages such as Python and Javascript, Key/Value Pair).
// Line 71 declares the function that adds an address to the (empty) inheritance array we just created and then sets the inheritance to be provided to this address.
// We added the the “onlyOwner” modifier we added to this function, which means that only the owner of the money can distribute the funds
// Finally we create the payout function, i.e. the actual transfer of the funds
function payout() private mustBeDeceased {
for (uint i=0; i<wallets.length; i++) {
wallets[i].transfer(inheritance[wallets[i]]);
}
}
function deceased() public payable onlyOwner {
isDeceased = true;
payout();
}
}
Solidity error message i receive when i try to transfer the payment to the payee
I executed your code and examine in depth. Note that currently remix and solidity does not show good and meaningful error messages.
The problem here is your constructor function is payable:
constructor() public payable {
owner = msg.sender;
fortune = msg.value;
isDeceased = false;
}
And if you execute constructor without any value it will execute also the setInheritance will execute without error and when you try to run the deceased function which is another payable function, then the things will blast. The remix will say the constructor is payable but did not sent any value.
Please try to send some value if you want to run any payable function. Here you can write value for payable functions.
Hope it helps.

Extending TypeError

PHP7 introduced the TypeError "exception" (I know it implements throwable rather than extends exception so it's not strictly speaking an exception, but they behave in essentially the same way as far as I can tell) which gets thrown if you enable strict mode for function parameter type hinting.
declare (strict_types = 1);
function square (int $val) : int
{
return $val * $val;
}
var_dump (square ("123"));
The above code should throw a TypeError, which you can optionally catch and attempt to recover from or terminate execution, depending on what is the most appropriate course of action to take.
However, TypeError seems like it would be a bit too generic, and it would be nice if you were able to extend it to convey a bit more information about the failure that occurred:
class TypeNotIntError extends TypeError {} // Throw this when an int was expected
class TypeNotFloatError extends TypeError {} // Throw this when a float was expected
class TypeNotStringError extends TypeError {} // Throw this when a string was expected
// etc
It should be possible to extend TypeError like this because the PHP documentation doesn't state that it's a final class. However, while you can extend TypeError there doesn't seem to be a mechanism that allows you to throw a child of TypeError without manually throwing one inside a function. As a TypeError would already be thrown by the engine if you pass in an invalid parameter type, the ability to extend TypeError seems pretty limited to me.
Is it possible to tell PHP what sort of TypeError subclass a function/method should throw if passed an invalid parameter type? If so, how?

Groovy end exception different from exception thrown

I am running into an extremely strange behavior in Groovy. When I throw an exception from a closure in a Script, the end exception that was thrown was different.
Here are the code and the details:
public class TestDelegate {
def method(Closure closure) {
closure.setResolveStrategy(Closure.DELEGATE_FIRST);
closure.delegate = this;
closure.call();
}
public static void main(String[] args) {
// Make Script from File
File dslFile = new File("src/Script.dsl");
GroovyShell shell = new GroovyShell();
Script dslScript = shell.parse(dslFile);
TestDelegate myDelegate = new TestDelegate();
dslScript.metaClass.methodMissing = {
// will run method(closure)
String name, arguments ->
myDelegate.invokeMethod(name, arguments);
}
dslScript.metaClass.propertyMissing = {
String name ->
println "Will throw error now!"
throw new MyOwnException("errrrror");
}
dslScript.run();
}
}
class MyOwnException extends Exception {
public MyOwnException(String message) {
super(message);
}
}
Script.dsl:
method {
println a;
}
So the plan is that when I run the main() method in TestDelegate, it will run the DSL script, which calls for the method method(). Not finding it in the script, it will invoke methodMissing, which then invokes method() from myDelegate, which in turns invoke the closure, setting the delegate to the testDelegate. So far, so good. Then the closure is supposed to try printing out "a", which is not defined and will thus set off propertyMissing, which will will throw MyOwnException.
When I run the code, however, I get the following output:
Will throw error now!
Exception in thread "main" groovy.lang.MissingPropertyException: No such property: a for class: TestDelegate
Now, it must have reached that catch block, since it printed "Will throw error now!" It must have thrown MyOwnException too! But somewhere along the lines, MyOwnException was converted to MissingPropertyException, and I have no idea why. Does anyone have any idea?
P.S. if I remove closure.setResolveStrategy(Closure.DELEGATE_FIRST) from TestDelegate#method(), the code acts as expected and throws MyOwnException. But I really need the setResolveStrategy(Closure.DELEGATE_FIRST) for my DSL project. And I would prefer to know the root cause of this rather than just removing a line or two and see that it works without understanding why.
I think this is what essentially happens: With a delegate-first resolve strategy, the Groovy runtime first tries to access property a on myDelegate, which results in a MissingPropertyException because no such property exists. Then it tries propertyMissing, which causes a MyOwnException to be thrown. Eventually the runtime gives up and rethrows the first exception encountered (a design decision), which happens to be the MissingPropertyException.
With an owner-first resolve strategy, propertyMissing is consulted first, and hence MyOwnException is eventually rethrown.
Looking at the stack trace and source code underneath should provide more evidence.