Minimalforwarder contract with relayer sets the "from address" to the contract address instead of the req.from during execution

After using the example from the meta transaction on goerli
I minted some tokens
Anytime I tried sending the tokens it would only send from the tokens on the deployed minimal forwarder contract
I modified the data to contain the hex version of the raw transaction data
Then tried sending it but it got reverted because it was trying to send a token that was not on the contract
This the contract I created

I firstly tried sending a command which minted some tokens into the contract then yarn relay now sends the tokens on the contracts to another wallet

The deployed minimalforwarder contract address is
:computer: Environment

im using relayer


:1234: Code to reproduce

this is my sign.js
const { ethers } = require('hardhat');
const { signMetaTxRequest } = require('../src/signer');
const { readFileSync, writeFileSync } = require('fs');

const DEFAULT_NAME = 'sign-test';

function getInstance(name) {
const address = JSON.parse(readFileSync('deploy.json'))[name];
if (!address) throw new Error(Contract ${name} not found in deploy.json);
return ethers.getContractFactory(name).then(f => f.attach(address));

async function main() {
const forwarder = await getInstance('MinimalForwarder');
//const registry = await getInstance("Registry");

//const { NAME: name, PRIVATE_KEY: signer } = process.env;
const signer = "my privatekey";
const from = new ethers.Wallet(signer).address;
//console.log(`Signing registration of ${name || DEFAULT_NAME} as ${from}...`);
//const rege = [];
//const data = "0x2d0335ab000000000000000000000000be8df63b141013613bf89b3f8988fca413652841";
//const datas = rege.encodeFunctionData('register', [name || DEFAULT_NAME]);
const input = {
        from: "0xbe8DF63B141013613Bf89B3f8988FcA413652841",
        to: "0xBA62BCfcAaFc6622853cca2BE6Ac7d845BC0f2Dc",
        value: '0',
        gas: "50000",
        data: "0x23b872dd000000000000000000000000be8df63b141013613bf89b3f8988fca41365284100000000000000000000000000a8210c2b1d46277d81c2b892ecd7f49e091a930000000000000000000000000000000000000000000000056bc75e2d63100000"

const result = await signMetaTxRequest(signer, forwarder, input);

writeFileSync('tmp/request.json', JSON.stringify(result, null, 2));
console.log(`Signature: `, result.signature);
console.log(`Request: `, result.request);


if (require.main === module) {
main().then(() => process.exit(0))
.catch(error => {

my signer.js
const ethSigUtil = require('eth-sig-util');

const EIP712Domain = [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'verifyingContract', type: 'address' }

const ForwardRequest = [
{ name: 'from', type: 'address' },
{ name: 'to', type: 'address' },
{ name: 'value', type: 'uint256' },
{ name: 'gas', type: 'uint256' },
{ name: 'nonce', type: 'uint256' },
{ name: 'data', type: 'bytes' },

function getMetaTxTypeData(chainId, verifyingContract) {
return {
types: {
domain: {
name: 'MinimalForwarder',
version: '0.0.1',
primaryType: 'ForwardRequest',

async function signTypedData(signer, from, data) {
// If signer is a private key, use it to sign
if (typeof(signer) === 'string') {
const privateKey = Buffer.from(signer.replace(/^0x/, ''), 'hex');
return ethSigUtil.signTypedMessage(privateKey, { data });

// Otherwise, send the signTypedData RPC call
// Note that hardhatvm and metamask require different EIP712 input
const isHardhat = data.domain.chainId == 31337;
const [method, argData] = isHardhat
    ['eth_signTypedData', data] : ['eth_signTypedData_v4', JSON.stringify(data)]
return await signer.send(method, [from, argData]);


async function buildRequest(forwarder, input) {
const nonce = await forwarder.getNonce(input.from).then(nonce => nonce.toString());
return { value: 0, gas: 1e6, nonce, ...input };

async function buildTypedData(forwarder, request) {
const chainId = await forwarder.provider.getNetwork().then(n => n.chainId);
const typeData = getMetaTxTypeData(chainId, forwarder.address);
return {...typeData, message: request };

async function signMetaTxRequest(signer, forwarder, input) {
const request = await buildRequest(forwarder, input);
const toSign = await buildTypedData(forwarder, request);
const signature = await signTypedData(signer, input.from, toSign);
return { signature, request };

module.exports = {

Hey @Gbenga_Tolulope,

Sorry for the late reply, can you move your scripts to a Github Gist so I can take a look more closely? Unfortunately, the format isn't really good and I think there's some missing info on your report (or I'm getting lost).

From what I see, you got the from values correct, but I'll need an executable example to help you further.
Can you please help us providing that?