0

I need to send a certain quality of ether from the smart contract to an address, but the problem is that I need that along with that transaction I need information to be recorded in the blockchain for later access. How do I make sure that only the information I want is recorded along with the transaction?

I was trying to do something like this:

  function Transaction(address payable _to, bytes memory info) public payable {

    //_to.transfer(msg.value);//this works but only performs the transfer

    (bool sent, bytes memory data) = _to.call{value: msg.value}(info);
    require(sent, "Failed to send Ether");
  }

But with this it doesn't work and I don't understand how to register only the information (info) in the blockchain.

enter image description here

Turning TX DATA 0x1e6595ab0000000000000000000000003d1188b926bee218b7980fa23b3c01a222e9806c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000045445535400000000000000000000000000000000000000000000000000000000 to string the result is:

enter image description here

What are the characters before? And how do I make sure they are not stored in the blockchain? But with this it doesn't work because if you turn TX DATA 0x1e6595ab0000000000000000000000003d1188b926bee218b7980fa23b3c01a222e9806c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000045445535400000000000000000000000000000000000000000000000000000000

to string the result is:

3
  • It is not possible from a contract since ether transfers are "internal transactions", they don't have a visible txdata from block explorers. As said by Rob the usual solution is to generate events. If you really want the message to appear in a transaction's data field then you have use a non-contract account. – Ismael May 12 at 4:41
  • I need to access the information later (i.e. access by address the transaction) and not at that time so it needs to be logged. The problem is that it gets logged but along with it come some strange characters and I don't know how to avoid that Shouldn't that be automatic when sending the transaction? – Lara Trindade May 12 at 18:33
  • To interact with a contract you have to send the function id and parameters through txdata field. They are encoded using solidity ABI. It should be possible to send a text and use the fallback function for that case. – Ismael May 12 at 20:00
0

The usual pattern is to emit an event:

contract Thingy {

  event DidSomething(address sender, address to, uint amount, bytes info);

  ...

  function Transaction(address payable _to, bytes memory info) public payable {
    emit DidSomething(msg.sender, _to, amount, info);
    
    _to.transfer(msg.value);//this works but only performs the transfer
    (bool sent, bytes memory data) = _to.call{value: msg.value}(info);
    require(sent, "Failed to send Ether");
  }

Notice how the input arguments are echoed in the event emitter. Given that the function is deterministic, this ensures that the state can be recreated externally, in theory. Also, no event will be emitted if the transaction fails at the require() statement because failed transactions don't alter the blockchain. Finally, treat it as an "effect" in the "checks, effects, interactions" pattern and invoke it prior to the external call for best results. That issue is subtle and out-of-scope for this question, so just a PSA and a hint about a heuristic that help keep it sensible.

Now, if the contract will need to act logically, i.e. branch or compute elsewhere based on the content of the input, the event log will not serve this purpose. Contracts can't access it. If you can't complete all of the work (should try) within the function while the information is easily accessed, then you would have to store the details for later.

Storage will be much more expensive (gas). The precise organization will depend on what you need back and when i.e. how the algorithm works.

Have a look over here for some ideas: Are there well-solved and simple storage patterns for Solidity?

You might hold inputs in a struct:

struct Thing {
   address sender, 
   address to,
   uint amount,
   bytes info
}

Then you would need to organize those into arrays or mappings to make them findable when needed.

For example, for each user there is an array of transactions they sent. <== this part depends on what you need to accomplish. As stated, it would be:

mapping(address => Thing[]) userThings;

Hope it helps.

4
  • But I need to store the information along with the transaction (in the TX DATA field) and not in a structure. The problem is that I get those characters before it that I don't know what the information is, and I just stored "info". – Lara Trindade May 11 at 21:46
  • The first four bytes are the function signature. Basically hash("Transaction(address,bytes)"). It will be less trouble to ignore and store than to strip them out. – Rob Hitchens May 13 at 15:20
  • bytes info is a way of accepting arbitrary data. You should use that when you don't know the layout of the information (useful for some cases). If you do know the layout, then use separate arguments. – Rob Hitchens May 13 at 15:22
  • I have failed to answer your question, please clarify what you're trying to accomplish. – Rob Hitchens May 13 at 15:23

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.