0

In an effort to reduce gas costs for users, I'm looking for a way to delegate certain transactions to a contract owner so that the owner makes a transactions that would have been otherwise sent by the user. So instead of sending a transaction directly to the blockchain, the user could sign a message in MetaMask and send the message as an authorization to the server, which would then send a transaction to the blockchain, assuming other conditions are met.

However, to provide maximum assurance to users that only authorized transactions are processed/sent by the contract owner, I'd like to be able to unpack the signed message within the contract so that the following are verified:

1) The user's address

2) The transactions data

At a high level, the solidity function would look something like this.

function processDelegatedTransaction(
    address userAddress,
    bytes32 msgHash,
    uint8 v,
    bytes32 r,
    bytes32 s,
    uint16 param1,
    uint16 param2
) public requireOwner {

    require(userAddress == ecrecover(msgHash, v, r, s));

    // Do something else to verify that param1 and param2 are packed in msgHash
}

The require statement should take care of #1 above, but #2 is the issue.

The message signing process could encode multiple parameters into a single uint, which would be included in the hash and then, if I'm able to unpack the hash, decode them similarly to the method described here:

https://medium.com/@novablitz/storing-structs-is-costing-you-gas-774da988895e

So the only sticking point is being able to extract the params from the hash or recreate the hash from the params. Is this possible?

2

The typical solution here is to not accept a hash at all but just recreate it. Something like this:

function processDelegatedTransaction(
    address userAddress,
    uint8 v,
    bytes32 r,
    bytes32 s,
    uint16 param1,
    uint16 param2
) public requireOwner {
    bytes32 msgHash = keccak256(abi.encodePacked(param1, param2));
    require(userAddress == ecrecover(msgHash, v, r, s));
}

Depending on how you're producing the signature in the first place, you may need to do either EIP712 or prefixed (geth/Parity-style) messages. For the latter, see this example:

https://programtheblockchain.com/posts/2018/02/17/signing-and-verifying-messages-in-ethereum/

  • Thanks - I got the prefixed version working after some trial an error, but I'd like to get the EIP712 version working, however, the only example I can find uses an older version of web3. I searched for EIP712 on ethereum.stackexchange and there only 3 total questions, including this one! So I opened up a new question about how to implement with current web3. ethereum.stackexchange.com/questions/74027/… If you have any other resources to share, they would be appreciated. – SuperCodeBrah Aug 19 at 7:43
  • I just needed to update my web3 and it works now. I was using 1.0.0-beta.55, and upgraded to 1.2.1 (looks like 1.2.0 was released < 1 month ago). Thanks for pointing me in the right direction. – SuperCodeBrah Aug 19 at 20:27

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.