0

I am new to solidity. Anyway, I have written the following smart contract:

pragma solidity >=0.4.22 <0.7.0;

contract SP {

    address BlockAddress;
    bytes32 _Mhash;

    function verifyHash_ASM(bytes32 _MHash) public returns (address payable Validator_address) {

        bytes4 sig = bytes4(keccak256("verifyHash(string)"));
        assembly {
            // move pointer to free memory spot
            let ptr := mload(0x40)
            // put function sig at memory spot
            mstore(ptr,sig)
            // append argument after function sig
            mstore(add(ptr,0x04), _MHash)

            let result := call(
              15000, // gas limit
              sload(BlockAddress_slot),  // to addr. append var to _slot to access storage variable
              0, // not transfer any ether
              ptr, // Inputs are stored at location ptr
              0x20, // Inputs are 32 bytes long
              ptr,  //Store output over input
              0x20) //Outputs are 32 bytes long

            if eq(result, 0) {
                revert(0, 0)
            }

            Validator_address := mload(ptr) // Assign output to Validator_address var
            mstore(0x40,add(ptr,0x24)) // Set storage pointer to new space

        }
        //PayTokens(Validator_address, User_address, RepTokens);
        //return Validator_address;
    }

When I call the verifyHash_ASM function and parse the byte32 value 0x33c897fb3febb48f0a8a9ff79518057a9943ed879d644bba81a8a1050ccfaa4f which is equivalent to the one assigned in another contract and call the same function in that contract, I get the following error:

"transact to SP.verifyHash_ASM 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."

The status is: "0x0 Transaction mined but execution failed"

Please note that I executed the function without values in Remix. I have also tried executing this by adding gas values and changing the function to "payable",but I still got this error.

The compiler I am using is 0.5.11 and the execution environment is JavaScript VM in Remix.

Your help and support is much appreciated

Thank you

1

It looks like you have two bugs. First:

bytes4 sig = bytes4(keccak256("verifyHash(string)"));

The actual function takes a bytes32, not a string, so this should be:

bytes4 sig = bytes4(keccak256("verifyHash(bytes32)"));

Second:

0x20, // Inputs are 32 bytes long

The input is actually 36 bytes long. 4 bytes for the function selector, and then a single bytes32 parameter. So this should be:

0x24, // Inputs are 36 bytes long

Once I made those changes, this code worked as expected.


As an aside, is there a reason you're doing this in assembly? I would have expected something more like this:

interface IValidator {
    function verifyHash(bytes32 hash) external view returns (address);
}

contract SP {
    IValidator validator;
    ...
    function verifyHash(bytes32 hash) external view returns (address) {
        return validator.verifyHash(hash);
    }
}
  • Thanks a lot. That gets rid of the issue. I should have noticed that. Well, I am actually a novice at this, and I saw that I could use assembly to return values from a function in another contract. Anyway, my idea was to call a different contract that has a different address and get the return value from it to the local contract. Btw, if I uncomment "verifyHash_ASM(_Mhash);" line inside the "ReadMerkelHash" function in the SP contract (it is commented in this), it again gives the same error. Is it allowed in solidity to call a function inside a function, this way? – Deepal Sep 11 at 4:59
  • With my fixes, uncommenting that line works fine for me. I can call readMerkelHash with the same bytes32 value, and the transaction completes successfully. – smarx Sep 11 at 5:04
  • Thanks a lot again. Yes, it does. I had put a line like this inside the verifyHash_ASM function as "PayTokens(Validator_address, values.RepTokens);" So what should happen is, when I enter input values and call the readMerkleHash, it should do its thing and call verifyHash_ASM. Then verifyHash_ASM should do its thing and then call the PayTokens function. But when I do this, I get that error. – Deepal Sep 11 at 5:19
  • That's really a separate question. I'd suggest isolating that bit of code in a simpler example and posting it as a new question. (Hint: the issue is likely confusion about transferring ether versus tokens. Your code transfers ether, and your smart contract probably has an insufficient balance to do so.) – smarx Sep 11 at 6:50
  • That was really the issue. Thank you so much. When I changed the construct to payable and deployed the smart contract with one ether it worked – Deepal Sep 11 at 8:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.