1

I'm new in Solidity, therefore if I have a wrong concept of anything kindly do explain.

I'm working for a personal escrow smart contract that should include these functions:

1- function deposit from the owner wallet to the smart contract

2- function gethash this function requires (amount) and returns hashcode

  • amount should not equal 0

3- function transfer amount to address this function requires (hashcode, address)

  • the amount is taken from the hashcode generated by gethash function

  • check that hashcode is not in conflict or used before

4- function withdraw to withdraw all money in the smart contract to the owner

I use this code :

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

contract mypayable {

   // Payable address can receive Ether
    address payable public owner;

    // Payable constructor can receive Ether
    constructor() payable {
        owner = payable(msg.sender);
    }

    function deposit() public payable {}

  uint deposit_count;
  mapping(bytes32 => uint256) balances;
  function getHash(uint amount) public view returns(bytes32 result){
    return keccak256(abi.encodePacked(msg.sender, deposit_count, amount,block.timestamp));
  }

  
  function transferto(address payable _to, bytes32 trx_hash, uint amount ) external {

    balances[trx_hash] = amount;
    deposit_count++;

      // Transaction hash cannot be empty
    require(trx_hash[0] != 0, "Transaction hash cannot be empty!");
    // Escrow amount cannot be equal to 0
    require(amount != 0, "Escrow amount cannot be equal to 0.");

    // Transaction hash is already in use
    require(balances[trx_hash] == 0, "Unique hash conflict, hash is already in use.");
    // Transaction hash cannot be empty
    require(trx_hash[0] != 0, "Transaction hash cannot be empty!");
    // Check if trx_hash exists in balances
    require(balances[trx_hash] != 0, "Escrow with transaction hash doesn't exist.");
    // Transfer escrow to sender
   // require(_token.transfer(msg.sender, balances[trx_hash]), "Escrow retrieval failed!");
    (bool success, ) = _to.call{value: balances[trx_hash]}("");
        require(success, "Failed to send Ether");

    // If all is done, status amounts to 0
    balances[trx_hash] = 0;
  }

    function withdraw() public {
        // get the amount of Ether stored in this contract
        uint amount = address(this).balance;

        // send all Ether to the owner
        // Owner can receive Ether since the address of the owner is payable
        (bool success, ) = owner.call{value: amount}("");
        require(success, "Failed to send Ether");
    }


}

  • functions deposit and withdraw work correctly no issues

  • function gethash returned hash code correctly and changeable

  • I guess the whole issue in function transferto:

firstly: I added parameter {amount} because I didn't know how to get the amount value from gethash function

second: I faced this error when I tried the transferto function

Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending? 
execution reverted: Unique hash conflict, hash is already in use.
{
  "originalError": {
    "code": 3,
    "data": "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002d556e69717565206861736820636f6e666c6963742c206861736820697320616c726561647920696e207573652e00000000000000000000000000000000000000",
    "message": "execution reverted: Unique hash conflict, hash is already in use."
  }
}

What is the best way to generate and store code/hashcode including amount value and check it in another function like transferto function?

so the withdrawal will input his address and code I provide it and he will receive the exact amount in gethash function

if there's something missing please tell me to clear more Thanks in Advance

---------------------------- update

I would like to thank (Jeremy Then) for his helping

the message error was gone, but there's something wrong

the hashcode is valid forever not expired I can send many transactions in the same hashcode and this is not logical first transaction second transaction

Also, If I input the amount in the gethash function with different values of the amount in transferto, the code will take the amount value of the transferto function different values

I would like if can take the amount from the gethash function and delete the parameter (amount) from the function transferto.

1 Answer 1

1

The first thing that you are doing in the transferto function is:

balances[trx_hash] = amount;

But then, you do this check:

require(balances[trx_hash] == 0, "Unique hash conflict, hash is already in use.");

Which is not compatible with balances[trx_hash] = amount;, becase you already added data to the balances[trx_hash], and then you require it to be empty, but it's not empty because you just assigned an amount to it. That's the problem.

Maybe you need to add require(balances[trx_hash] == 0, "Unique hash conflict, hash is already in use."); before balances[trx_hash] = amount;, what do you think?

By the way, I don't think this check is right:

require(trx_hash[0] != 0, "Transaction hash cannot be empty!");

Because it is literally just checking the first byte of the trx_hash, and in really that first byte could be 0 and all the other bytes could have value.

For example, this check would fail for a valid hash like this: 0x00f6c4584609ab7d77c6af1a7d07a765ffb7d8f5bcec07c613a6c9f6fb00729b, notice the first byte is 00, but it's a valid hash that the keccak256 could return.

So, better do this:

require(trx_hash != 0, "Transaction hash cannot be empty!");

Here we are comparing the whole 32 bytes of trx_hash value with 0. If all the 32 bytes of trx_hash are empty, then its value is 0 and we can compare it with 0.

For your transferto function to work, it should look something like this:

function transferto(address payable _to, bytes32 trx_hash, uint amount ) external {

    require(balances[trx_hash] == 0, "Unique hash conflict, hash is already in use.");

    balances[trx_hash] = amount;
    deposit_count++;

      // Transaction hash cannot be empty
    require(trx_hash != 0, "Transaction hash cannot be empty!");
    // Escrow amount cannot be equal to 0
    require(amount != 0, "Escrow amount cannot be equal to 0.");

    // Transaction hash is already in use
    
    // Transaction hash cannot be empty
    //require(trx_hash[0] != 0, "Transaction hash cannot be empty!");
    // Check if trx_hash exists in balances
    require(balances[trx_hash] != 0, "Escrow with transaction hash doesn't exist.");
    // Transfer escrow to sender
   // require(_token.transfer(msg.sender, balances[trx_hash]), "Escrow retrieval failed!");
    (bool success, ) = _to.call{value: balances[trx_hash]}("");
        require(success, "Failed to send Ether");

    // If all is done, status is amounted to 0
    balances[trx_hash] = 0;
  }
2
  • 1
    Thank you for answering I did what you mention and the error is gone but there's something wrong I get the hash code and tried to transfer I input the same address, amount, and hashcode many times, and its transfer every time the hashcode should be invalid after being used one time excuse my bad English Sep 27, 2022 at 19:53
  • Check the update. Sep 27, 2022 at 20:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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