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
0x7AeB71B22B11Ce7b31008AdD947dFe425F288156
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
Environment
im using relayer
Details
Code to reproduce
this is my sign.js
//s
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 => {
console.error(error);
process.exit(1);
});
}
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: {
EIP712Domain,
ForwardRequest,
},
domain: {
name: 'MinimalForwarder',
version: '0.0.1',
chainId,
verifyingContract,
},
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 = {
signMetaTxRequest,
buildRequest,
buildTypedData,
};