Non custodian transaction relay

Introduction

Meta transaction are based on message signing. A smart contract is deployed with the public address of an EOA as parameter. The contract will be able to execute transactions on behalf of this EOA. The owner of the EOA will have to generate a message containing the information of the transaction he want to execute and to sign the message with its EOA.

1- Deploy a relayable identity smart contract

Use Rockside API to deploy a relayable identity smart contract for your EOA account:

curl-XPOST\
2 https://api.rockside.io/ethereum/ropsten/contracts/relayableidentity \
3 -H 'apikey: YOUR_API_KEY' \
4 -d '{"account": "YOUR_EOA_PUBLIC_ACCOUNT"}'

You will get:

1{
2 "address": "0x60d44d28c826cff5d05ee57526e20103cdac1c9a"
3 "transaction_hash":"0xa51fdb4b79c45fbe9bf6df5a822814f6ad47bf9dfad4bb2b"
4}

Keep the relayable indentity contract address, you will need it to send transaction.

2- Get the nonce for your EOA on your relayable identity

To avoid replay attack, the relayable identity manage a nonce for each authorized EOA.

To retrieve the nonce call Rockside API:

curl -X POST \
https://api.rockside.io/ethereum/ropsten/contracts/relayableidentity/RELAYABLE_CONTRACT_ADDRESS/nonce \
-d '{"account":"PUBLIC_ADDRESS_OF_YOUR_EOA"}'\
-H 'Content-Type: application/json' \
-H 'apikey: YOUR_APIKEY'

You should get:

{
"nonce": "0"
}

3- Create and sign your transaction message

We will use a small nodejs program to generate the signature of the transaction message.

Create a new project with npm:

npm init

You need ethereumjs-util and ethereumjs-abi.

npm install ethereumjs-util -save
npm install eth-sig-util -save

In your index.js file put the following code and replace values for "YOUR_PRIVATE_KEY" and "YOUR_CONTRACT_ADDRESS" and the correct nonce value.

var ethUtil = require('ethereumjs-util')
var sigUtil = require('eth-sig-util')
const privateKey = new Buffer("YOUR_PRIVATE_KEY", "hex")
const signerAddressBuffer = ethUtil.privateToAddress(privateKey);
const signerAddress = ethUtil.bufferToHex(signerAddressBuffer)
console.log('EOA Address :', signerAddress)
var identityAddress = 'YOUR_CONTRACT_ADDRESS'
var destinationAddress = '0x2c68bfBc6F2274E7011Cd4AB8D5c0e69B2341309'
var transactionValue = '0x0'
var transactionData = []
var idenityNonce = 0 //THE NONCE FOR YOUR EOA on the identity
const EIP712Domain = [
{ type: "address", name: "verifyingContract" },
{ type: "uint256", name: "chainId" }
]
const txMessageType = [
{ type: "address", name: "signer" },
{ type: "address", name: "to" },
{ type: "uint256", name: "value" },
{ type: "bytes", name: "data" },
{ type: "uint256", name: "nonce" }
]
const domainData = {
verifyingContract: idenitityAddress,
chainId: 3
};
var txMessage = {
signer: signerAddress,
to: destinationAddress,
value: transactionValue,
data: transactionData,
nonce: identityNonce
};
const txMessageData = {
types: {
EIP712Domain: EIP712Domain,
TxMessage: txMessageType,
},
domain: domainData,
primaryType: "TxMessage",
message: txMessage
};
const sig = sigUtil.signTypedData(privateKey, { data: txMessageData })
console.log("SIGNATURE: "+sig)

By running the code you get:

node index.js
EOA Address : 0x2c68bfbc6f2274e7011cd4ab8d5c0e69b2341309
SIGNATURE: 0x0944d98fb85729bf4692c9ee9c8221b70a33a19da074648d4e6a811861fc94e35bd715541319a437cb3ef1a2f13aa4ddf76c55297093682da86fca6fdd33a1191b

4- Use Rockside to Relay your transaction

Call Rockside API to relay your transaction:

curl -X POST 'https://api.rockside.io/ethereum/ropsten/contracts/relayableidentity/RELAYABLE_CONTRACT_ADDRESS/relayExecute' \
-d '{"from":"SIGNER_ADDRESS", "to":"DESTINATION_ADDRESS", "value":"0x0", "signature":"SIGNATURE_OF_YOUR_MESSAGE"}' \
-H 'Content-Type: application/json' \
-H 'apikey: YOUR_APIKEY'

You will get:

{"transaction_hash":"0xb1b5ec87c6b24e3f3bc389b2e1dca4d0c8bcbd52ba153508b89342a83f0fa977"}

It's the hash of your transaction you can follow it on etherscan.