{"_id":"@anydotcrypto/metatransactions","_rev":"52-98c4ba1aadcf6a2f1560892dea891f68","name":"@anydotcrypto/metatransactions","dist-tags":{"latest":"0.0.20","next":"0.0.13","experimental":"0.0.15-6"},"versions":{"0.0.1":{"name":"@anydotcrypto/metatransactions","version":"0.0.1","description":"A minimal approach for meta-transaction support.","main":"build/index.js","types":"build/index.d.ts","scripts":{"build-test":"npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./build ./build/**/*.json","execute":"ts-node src/ts/deployment.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run runtest -- --timeout='30000'","prepublish":"tsc"},"devDependencies":{"@any-sender/client":"^0.2.0-beta.0","@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","bn.js":"^5.1.1","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","ethers":"^4.0.43","install":"^0.13.0","mocha":"^7.0.0","np":"^6.2.1","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"dependencies":{},"gitHead":"026740746c694fe615b4efae8bebd187d2a9f92c","_id":"@anydotcrypto/metatransactions@0.0.1","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-3eRUlhtrbGydm5tsVKt5KmcHdjZzss0Inr2sD0xVI+eXP2mq5tGXMisLRhV3zOWiBVNo3Q46IldWxCwGSRzzOA==","shasum":"e7d4b49fba2b65f9982589da6ecaad68af93de28","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.1.tgz","fileCount":29,"unpackedSize":368183,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelHL4CRA9TVsSAnZWagAAigwP/2SZ7UsK7ClDHaJwDxh3\nxMh6S41gRMf2pWUT87EETN1hz+vvmHSUypjwxSXhyMAVsiWTeAv6rNXSyHJB\n7nzG9KJlq7yu29IuvWUwUqPHLHsnXf5dNnR4oaCaaqeJgnRQJgoSZDaaZxq1\np4pCT2ZzbySBVqmAIHxz1s+qaJJ6dsYJ5Hp4ZNCTzNhncCCreFQNUfPdO3jA\noZbcVoxez2s6++pZYOluFCLIBZYZyLAvZA0p4YhqwU+B6LBN9kAg9VRzys4P\nEIxtKI8Vf4W3gGSSUXR/r9XrrD3kt7KRk+WfixrbX3OEw1GxIPdmmtAM1o4T\noPYHE0CIcgKbOXwZQ4RPePK3z2nOlLbwAMkot6s+MdMFEY0febOHgXmgHwfz\ni+/90DGtQ/168xWc3sKoi8nss4/S99hnRnNLWOb9l3i0sbDejGOaApR+1XM1\nmeUCS7BwBcPXx8lpBO7j7Jpa+TouZpRTP6Z9IEx0VKVlYzzQm3Tb5GHlZNzv\ny/zeTiBdCpg2A4IGAh+ac0b5Rrhx0AQf9wIK2XjyCBbOpxCdCChaV0of/OyS\n37A4NU8mWgWRmRLOHX8zqvU+yPMUmyIo9dIn/CRUb5AiRxGtFhYa13anBMPh\nwSKGgmDu9gUerEL3hMnyUMEgcRl4oQ55oISa4khzwmJJmLBJTYBuYFLSJUPd\nMV1Q\r\n=gIx3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH+Fj+N9Eai2PJ8B7DfuoEJLyKixoKCdt3BYEs4qEh5TAiB09eHRBIhOXKPtdRaQpNOS/blQSz++hkaQU/bkefn/1w=="}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.1_1586787064159_0.042887588544344935"},"_hasShrinkwrap":false},"0.0.2":{"name":"@anydotcrypto/metatransactions","version":"0.0.2","description":"A minimal approach for meta-transaction support.","main":"build/index.js","types":"build/index.d.ts","scripts":{"build-test":"npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./build ./build/**/*.json","execute":"ts-node src/ts/deployment.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run runtest -- --timeout='30000'","prepublish":"tsc"},"devDependencies":{"@any-sender/client":"^0.2.0-beta.0","@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","bn.js":"^5.1.1","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","ethers":"^4.0.43","install":"^0.13.0","mocha":"^7.0.0","np":"^6.2.1","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"dependencies":{},"gitHead":"8b77a12ed028509f866a85d44bee12b215303534","_id":"@anydotcrypto/metatransactions@0.0.2","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-CnZOuMjB2YJ3GApnksBMop4iKyEnhfbJSiwwSiLSVwBrnJjkyYM2GxaK/etP/n5JiFncWsSrlv4EWF+Kqc5FHQ==","shasum":"fb23b3f6acb877cf3f7b7133b6ef80ac715f5514","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.2.tgz","fileCount":29,"unpackedSize":368183,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelHZiCRA9TVsSAnZWagAAndgP+gLbFPOd3q+VPdjbzCck\n4qvU00mLNP5dYz1UwZpiC5AwIEqCYY/+iI/CKk9//FF5WkLsuZOBLh+NcjWj\n1r9UyRcCp44dMD2lgXD8fYJNQ95TkZA7fClIqPWTCOfFpDFOfp45WCEtxCQx\nQbPyvQR8CCrbyuwWH+xwaRqYevEDyt4BiOIF/OQv9h0HgmNxf/IHASoIWZsX\ncChWMDK7u1DF50y2ZgPuDfvcFWtQ/oEAQYLnW3umSS0hjbLeTFFFj2x6xm3L\nI6VH64tArQeRiO4GCGw8DXp+xGAd9AvFc3+BbHLIbJOCPup8F2+OkkP/Doxe\nP0T9CwHhUSixYedlUQHYaXyKkg+HrI2V67vh14cTIOHAUwSTRr2NWpNhJzZP\nSzIzHoHuX6+PUUDhQXXKgk4k/l09UEBPsdQSW304D0PYKrWM5RrODAclhu5C\nj2jIvW1lUGR1adwBFeRYwh1l0c7Wk3sWoCl/IYwkq+pHLhkiIZVnYKcSgexB\nhvUwUKJk60nrNshAVPYy9STThz7oVtkHPS7tvC0iY/xo/0Cn0Kqyw651AVHb\nggRmY9IVuzBPJqT873Auy7xZmbsKuLVDvW0jAJT5NcMcVWnU01+MS15a9++L\nQaRNT1Pb61vE/xe9x60vhZ3o4oMoqeVYt7dt0VZkH0zT6o3PncNbps9UEOGS\nJ8kJ\r\n=jk8d\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDtTCYcrJwGNoFCVimz6cFuKNYFqVp6Ee61STTOSKkCegIhAO36ReUaFhf4Gcv7E9KOzAomJ2Hp6ubVeB3uAiCoVHFp"}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.2_1586787937894_0.3596500297306138"},"_hasShrinkwrap":false},"0.0.3-0":{"name":"@anydotcrypto/metatransactions","version":"0.0.3-0","description":"A minimal approach for meta-transaction support.","main":"build/index.js","types":"build/index.d.ts","scripts":{"build-test":"npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./build ./build/**/*.json","execute":"ts-node src/ts/deployment.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run runtest -- --timeout='30000'","prepublish":"tsc"},"devDependencies":{"@any-sender/client":"^0.2.0-beta.0","@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","bn.js":"^5.1.1","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","ethers":"^4.0.43","install":"^0.13.0","mocha":"^7.0.0","np":"^6.2.1","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"dependencies":{},"readme":"# A Minimal Relay Hub (motivated by EIP-2585).\n \nThe fundamental problem we are solving is that an Ethereum transaction intertwines the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is not straight forward for Alice to pay the gas fee on bealf of Bob who wants to execute a command in a smart contract.  \n\nGenerally, the motivating reason to solve this problem is to allow a third party (Alice) to offer transaction infrastructure as a service to others (bob) in a non-custodial manner. This is useful for wallet providers who can offer a better user-experience for customers while maintaining their self-custody and for most new projects who can plug-in an infura-like transaction API instead of re-building the infrastructure themselves. \n\nSo far, there are two prominent methods to solve the problem: \n- Contract accounts: Each user has a smart contract that forwards commands\n- \\_msgSender: Modify existing smart contracts to support accepting externally signed messages.\n\nThe problem, like all problems in Ethereum, is that there are several standard ways to implement it (roll-your-own proxy or roll-your-own permit). More often than not, existing solutions intertwine with the application and it is hard to generalise it. \n\nBut if we boil down the problem, what really needs to be solved is just replay protection for the meta-transaction. e.g. Is this the latest signed message by the user? And of course, has this signed message been seen before? \n\nOur goal is to provide a minimal forwarder that simply handles replay protection for the signer before forwarding the contract call: \n\n- Dual-solution: Support both contract accounts and \\_msgSender()\n- Client library: Provide a single client library for authorising a meta-transaction \n- Better-than-Ethereum Replay Protection: Experiment with more exciting repay protection to support concurrent and out-of-order transactions. \n\nOf course, this solution cannot help existing users who sign Ethereum transactions to authenticate via msg.sender for existing contracts. Going forward, it can help users who are willing to switch their identity to a contract account (msg.sender) or if contracts adopt the \\_msgSender() standard. \n \n \n## Replay Protection Hub\n\nWe have created a single class, RelayProtectionHub, that takes care of signing meta-transactions for the RelayHub / Contract Account. \n\nIt supports by default:\n- Replace by nonce (single queue)\n- Multinonce (multiple queues)\n- Bitflip \n\n### How to set up \n\nWe will cover how to set up the RelayHub as setting up a ContractHub is very similar.\n\nTo create your own relay hub: \n```\n  const relayHubFactory = new RelayHubFactory(admin);\n  const relayHubCreationTx = relayHubFactory.getDeployTransaction();\n  const relayHubCreation = await admin.sendTransaction(relayHubCreationTx);\n  const receipt = await relayHubCreation.wait(1);\n```\n\nTo connect to an existing relay hub: \n```\n  const relayHubAddress = \"0x0......\";\n  const relayHubFactory = new RelayHubFactory(admin);\n  const relayHub = relayHubFactory.attach(relayHubAddress);\n```\n\nTo set up the replay protection hub:\n\n```\n// Single queue \nconst hubReplayProtection = HubReplayProtection.multinonce(relayHub, 1);\n\n// Multi queue \nconst hubReplayProtection = HubReplayProtection.multinonce(relayHub, 10);\n\n// Bitflip\nconst hubReplayProtection = HubReplayProtection.bitFlip(relayHub);\n\n```\n\nIn the future, the RelayHub for Ropsten and Mainnet will be hard-coded into this library. As a developer, you will simply need to pick the appropriate replay protection. \n\n\n### How to sign a meta-transaction \n\nA meta-transaction has the following parameters:\n\n- Signer: The Wallet of the signer\n- Target address: The address of the target contract\n- Value: Quantity of ether to transfer (only useful for contract accounts)\n- Calldata: Encoded function to call and the appropriate data\n\nTo sign a meta-transaction:\n\n```\nconst callData = targetContract.interface.functions.test.encode([]);\n\nconst params = await hubReplayProtection.signMetaTransaction(\n  signer,\n  targetContract.address,\n  new BigNumber(\"0\"),\n  callData\n);\n```\n\nA list of parameters is returned which can be used to send the transaction: \n\n```\ninterface ForwardParams {\n  hub: string; // Relay hub (or contract account) address \n  signer: string; // Signer's address\n  target: string; // Target contract address \n  value: string; // Value to send \n  data: string; // Calldata for target\n  replayProtection: string; // Encoded replay protection \n  replayProtectionAuthority: string; // Address of replay protection authority \n  chainId: number; // ChainID\n  signature: string; // Signer's signature\n}\n```\n\nTo send off the meta-transaction, the relayer just needs to execute forward: \n\n```\nconst tx = relayHub.connect(sender).forward(params.target, params.value, params.data, params.replayProtection, params.replayProtectionAuthority, params.signer, params.signature);\n```\n\nWhile the application is alive, the last replay protection used for the signer will be remembered. If the application restarts, it will fetch the last used values from the hub contract. \n\nOf course, be careful that there is a race condition if there is a restart while some meta-transactions are still in-flight. A future release may inspect the pending pool for the relevant data, but for 99% of cases it is not necessary. \n\n\n## How to build and test\n \nWe need to install the NPM packages:\n\n```\nnpm i\n```\n\nThen we can simply build and test:\n\n```\nnpm run build && npm run test\n```\n\n\n","readmeFilename":"README.md","gitHead":"194e95ca6172ae6b54e8c25166e2634111e55786","_id":"@anydotcrypto/metatransactions@0.0.3-0","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-wihAxH9mwqgfynIB0/bH8iUWFzMX1sj9/vVMS6LaZhRz+pAvStn3akEiCd5MiOEj1rIdMWoB7n9UDVZlFoR9SQ==","shasum":"64ef23d4b09664385926e1a2960599f774f9e46e","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.3-0.tgz","fileCount":47,"unpackedSize":158758,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelH3yCRA9TVsSAnZWagAAs6cP/1Pu2fF9qasXsdZQ+4q4\nvzGWNOJrCSC4j0DgN5odE8hsTLBFZLv+MXlIiTA5I66oL5KSsxQ7ZyPT2mNh\nsbCGIYHj/Duviq3Qcw+UWr07T22dYTt8hxqC4D6Xa6G3oPKSi59b7XpVekh4\nChHZcmzBIGtU2oP+oUc7mKcEo+dZBo8tkljrEUCzacjrpTpI5m+7FkC8g0Cr\n5DE3yI57RS75CDO63fUqaeTyF60m08XhdUgdqFiDB77Fy6LY16i8+mR0wmou\n+HofdsugDKnmdZMb4NEH5DP4M4sBONFQYoduIpWVCpyUsNJNt0h/OiPFBrHt\nijVV5gicOPUqqx19OD7aJ7qio+pAyikyrKWlVWlT/zpMrJQZSXptFIDQglLa\nduOCtWDxNJ/77HFaHL/3rxWNz05rdTpmXaJjpt9iyXafwC50xDKr4vt7AsTp\n/BazhVMHEIgfcUGrr5bJg2OAV6DKsbTUl5tJ6sFqNfWwfs2uicYd8hGkSVEm\nFiZg6azh4JHma8S5V5F5sNYkMXGAHv/qLrgdEyOiBXz37Wnf2SqB/WY4nE3K\n/d75KPGM74KP6LkyvpI7/hJo1jEWyhQUTmIFW7WR14dIqP7l/BVVOijvuXsd\nQGqsJiQ2WDHhlDMf4EKyNSu8jZXrFqt5kYSOjjWCAUEgCAmRihCuuGLbt5Ne\ni1hD\r\n=KUjP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC+oNADL5ju6qfqQKqhTZ0IreQCnKGTZqw/p9Vzm0/0PwIgeCOZlLuIEAusPAbESsWyT81v5QYmanB4QjgR26meVUw="}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.3-0_1586789874074_0.612259149532548"},"_hasShrinkwrap":false},"0.0.3-1":{"name":"@anydotcrypto/metatransactions","version":"0.0.3-1","description":"A minimal approach for meta-transaction support.","main":"dist/src/index.js","types":"dit/src/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./build ./build/**/*.json && tsc -p tsconfig.json && cp -r ./build/*.d.ts ./dist/build && cp -r ./src/contracts ./dist/src/contracts","execute":"ts-node src/ts/deployment.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run runtest -- --timeout='30000'","prepublish":"rm -r ./dist && npm run build"},"devDependencies":{"@any-sender/client":"^0.2.0-beta.0","@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","bn.js":"^5.1.1","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","ethers":"^4.0.43","install":"^0.13.0","mocha":"^7.0.0","np":"^6.2.1","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"dependencies":{},"readme":"# A Minimal Relay Hub (motivated by EIP-2585).\n \nThe fundamental problem we are solving is that an Ethereum transaction intertwines the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is not straight forward for Alice to pay the gas fee on bealf of Bob who wants to execute a command in a smart contract.  \n\nGenerally, the motivating reason to solve this problem is to allow a third party (Alice) to offer transaction infrastructure as a service to others (bob) in a non-custodial manner. This is useful for wallet providers who can offer a better user-experience for customers while maintaining their self-custody and for most new projects who can plug-in an infura-like transaction API instead of re-building the infrastructure themselves. \n\nSo far, there are two prominent methods to solve the problem: \n- Contract accounts: Each user has a smart contract that forwards commands\n- \\_msgSender: Modify existing smart contracts to support accepting externally signed messages.\n\nThe problem, like all problems in Ethereum, is that there are several standard ways to implement it (roll-your-own proxy or roll-your-own permit). More often than not, existing solutions intertwine with the application and it is hard to generalise it. \n\nBut if we boil down the problem, what really needs to be solved is just replay protection for the meta-transaction. e.g. Is this the latest signed message by the user? And of course, has this signed message been seen before? \n\nOur goal is to provide a minimal forwarder that simply handles replay protection for the signer before forwarding the contract call: \n\n- Dual-solution: Support both contract accounts and \\_msgSender()\n- Client library: Provide a single client library for authorising a meta-transaction \n- Better-than-Ethereum Replay Protection: Experiment with more exciting repay protection to support concurrent and out-of-order transactions. \n\nOf course, this solution cannot help existing users who sign Ethereum transactions to authenticate via msg.sender for existing contracts. Going forward, it can help users who are willing to switch their identity to a contract account (msg.sender) or if contracts adopt the \\_msgSender() standard. \n \n \n## Replay Protection Hub\n\nWe have created a single class, RelayProtectionHub, that takes care of signing meta-transactions for the RelayHub / Contract Account. \n\nIt supports by default:\n- Replace by nonce (single queue)\n- Multinonce (multiple queues)\n- Bitflip \n\n### How to set up \n\nWe will cover how to set up the RelayHub as setting up a ContractHub is very similar.\n\nTo create your own relay hub: \n```\n  const relayHubFactory = new RelayHubFactory(admin);\n  const relayHubCreationTx = relayHubFactory.getDeployTransaction();\n  const relayHubCreation = await admin.sendTransaction(relayHubCreationTx);\n  const receipt = await relayHubCreation.wait(1);\n```\n\nTo connect to an existing relay hub: \n```\n  const relayHubAddress = \"0x0......\";\n  const relayHubFactory = new RelayHubFactory(admin);\n  const relayHub = relayHubFactory.attach(relayHubAddress);\n```\n\nTo set up the replay protection hub:\n\n```\n// Single queue \nconst hubReplayProtection = HubReplayProtection.multinonce(relayHub, 1);\n\n// Multi queue \nconst hubReplayProtection = HubReplayProtection.multinonce(relayHub, 10);\n\n// Bitflip\nconst hubReplayProtection = HubReplayProtection.bitFlip(relayHub);\n\n```\n\nIn the future, the RelayHub for Ropsten and Mainnet will be hard-coded into this library. As a developer, you will simply need to pick the appropriate replay protection. \n\n\n### How to sign a meta-transaction \n\nA meta-transaction has the following parameters:\n\n- Signer: The Wallet of the signer\n- Target address: The address of the target contract\n- Value: Quantity of ether to transfer (only useful for contract accounts)\n- Calldata: Encoded function to call and the appropriate data\n\nTo sign a meta-transaction:\n\n```\nconst callData = targetContract.interface.functions.test.encode([]);\n\nconst params = await hubReplayProtection.signMetaTransaction(\n  signer,\n  targetContract.address,\n  new BigNumber(\"0\"),\n  callData\n);\n```\n\nA list of parameters is returned which can be used to send the transaction: \n\n```\ninterface ForwardParams {\n  hub: string; // Relay hub (or contract account) address \n  signer: string; // Signer's address\n  target: string; // Target contract address \n  value: string; // Value to send \n  data: string; // Calldata for target\n  replayProtection: string; // Encoded replay protection \n  replayProtectionAuthority: string; // Address of replay protection authority \n  chainId: number; // ChainID\n  signature: string; // Signer's signature\n}\n```\n\nTo send off the meta-transaction, the relayer just needs to execute forward: \n\n```\nconst tx = relayHub.connect(sender).forward(params.target, params.value, params.data, params.replayProtection, params.replayProtectionAuthority, params.signer, params.signature);\n```\n\nWhile the application is alive, the last replay protection used for the signer will be remembered. If the application restarts, it will fetch the last used values from the hub contract. \n\nOf course, be careful that there is a race condition if there is a restart while some meta-transactions are still in-flight. A future release may inspect the pending pool for the relevant data, but for 99% of cases it is not necessary. \n\n\n## How to build and test\n \nWe need to install the NPM packages:\n\n```\nnpm i\n```\n\nThen we can simply build and test:\n\n```\nnpm run build && npm run test\n```\n\n\n","readmeFilename":"README.md","gitHead":"fe500076a489a8778f629f9e5092bdeeec5949dc","_id":"@anydotcrypto/metatransactions@0.0.3-1","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-QuxVs+L6EcXb0kX+49ocXaVCWkvS7t9IVkGFYuR2o6hjWs1raETJexW0kbz4uV4aRu97Np+Jy3XltKwBvsbv0g==","shasum":"3f480a8467135cd8609bc18432d79b7b97ba7f98","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.3-1.tgz","fileCount":62,"unpackedSize":187388,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelKqHCRA9TVsSAnZWagAAX1cQAIV17qDy5NlY3+gE934H\nOAkP+UJVQggooKzndxjimxroPuUJwGbHiZwkmxWSfLKdiZI2v3Gmh76fIiLd\nCzZKLGz60ylPukWnOPmsY0HnpegmcoNBgbui6yO5Lr8vw+35ZkWHl2aJi2yB\nGme/jPZWaNlMl6XqPCLFVvqDjfEsUNWdAMWZtO7nyf7pKiHfiEnjoife5FUY\nLWzYhhevSeYkpcmjqagv4kgSj3Td+mBvxgD8bmmDtYrKKz6KyhVFI3GB1Ran\nMqo4zSk2M/ucaxqpPzOP5QhVCykzK5wtdfZhW35sjN6JwwAUpoZGPS5bRasL\nO+C/If+RW5xlztcfFmD/kAmAaUA2wY2GuLdxg7rZgzy9JT1KD+cQAx0wMW3d\n46qvr8QMpPJ2yizV3+IArZ139yJkcsSrNYtM2FET+c6TXxMem+xxQpu3aLl6\nadnOlY/fROd9UeSC4jZ2F85lzOgg0uTDbDzrMsVBowr99s1VEcZWOnq6zVnK\nzI/Z8ovW2Hg0QsUevDTk73RjmGbskY/9MVoqRorRcZ5PsLrUBO8NVypeLPLm\nMKzsjHsuLij8W7Lrv/exffiIPrKnMP2DnKIkxx28jlKnahTJ74An3yZHjnZ1\n/bWTLhJqES0279xRpmyD3rJgECu5ofWueWlEMND9XiuIB1UKKWXoVzTaUZyv\nST9H\r\n=6j1q\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFVoA40+LMY6XqgERsx0rrloV6ZBDQLbyk4ZOi5HO8OWAiBSm4aV5aP3UTjv8zkdrBB57S0F0xw7A0pSxZoNS6ugcQ=="}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.3-1_1586801286612_0.6627807936751455"},"_hasShrinkwrap":false},"0.0.3-2":{"name":"@anydotcrypto/metatransactions","version":"0.0.3-2","description":"A minimal approach for meta-transaction support.","main":"dist/src/index.js","types":"dit/src/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts && tsc -p tsconfig.json && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/ts/deployment.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run runtest -- --timeout='30000'","prepublish":"rm -r ./dist && rm -r ./build && npm run build"},"devDependencies":{"@any-sender/client":"^0.2.0-beta.0","@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","bn.js":"^5.1.1","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","ethers":"^4.0.43","install":"^0.13.0","mocha":"^7.0.0","np":"^6.2.1","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"dependencies":{},"readme":"# A Minimal Relay Hub (motivated by EIP-2585).\n \nThe fundamental problem we are solving is that an Ethereum transaction intertwines the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is not straight forward for Alice to pay the gas fee on bealf of Bob who wants to execute a command in a smart contract.  \n\nGenerally, the motivating reason to solve this problem is to allow a third party (Alice) to offer transaction infrastructure as a service to others (bob) in a non-custodial manner. This is useful for wallet providers who can offer a better user-experience for customers while maintaining their self-custody and for most new projects who can plug-in an infura-like transaction API instead of re-building the infrastructure themselves. \n\nSo far, there are two prominent methods to solve the problem: \n- Contract accounts: Each user has a smart contract that forwards commands\n- \\_msgSender: Modify existing smart contracts to support accepting externally signed messages.\n\nThe problem, like all problems in Ethereum, is that there are several standard ways to implement it (roll-your-own proxy or roll-your-own permit). More often than not, existing solutions intertwine with the application and it is hard to generalise it. \n\nBut if we boil down the problem, what really needs to be solved is just replay protection for the meta-transaction. e.g. Is this the latest signed message by the user? And of course, has this signed message been seen before? \n\nOur goal is to provide a minimal forwarder that simply handles replay protection for the signer before forwarding the contract call: \n\n- Dual-solution: Support both contract accounts and \\_msgSender()\n- Client library: Provide a single client library for authorising a meta-transaction \n- Better-than-Ethereum Replay Protection: Experiment with more exciting repay protection to support concurrent and out-of-order transactions. \n\nOf course, this solution cannot help existing users who sign Ethereum transactions to authenticate via msg.sender for existing contracts. Going forward, it can help users who are willing to switch their identity to a contract account (msg.sender) or if contracts adopt the \\_msgSender() standard. \n \n \n## Replay Protection Hub\n\nWe have created a single class, RelayProtectionHub, that takes care of signing meta-transactions for the RelayHub / Contract Account. \n\nIt supports by default:\n- Replace by nonce (single queue)\n- Multinonce (multiple queues)\n- Bitflip \n\n### How to set up \n\nWe will cover how to set up the RelayHub as setting up a ContractHub is very similar.\n\nTo create your own relay hub: \n```\n  const relayHubFactory = new RelayHubFactory(admin);\n  const relayHubCreationTx = relayHubFactory.getDeployTransaction();\n  const relayHubCreation = await admin.sendTransaction(relayHubCreationTx);\n  const receipt = await relayHubCreation.wait(1);\n```\n\nTo connect to an existing relay hub: \n```\n  const relayHubAddress = \"0x0......\";\n  const relayHubFactory = new RelayHubFactory(admin);\n  const relayHub = relayHubFactory.attach(relayHubAddress);\n```\n\nTo set up the replay protection hub:\n\n```\n// Single queue \nconst hubReplayProtection = HubReplayProtection.multinonce(relayHub, 1);\n\n// Multi queue \nconst hubReplayProtection = HubReplayProtection.multinonce(relayHub, 10);\n\n// Bitflip\nconst hubReplayProtection = HubReplayProtection.bitFlip(relayHub);\n\n```\n\nIn the future, the RelayHub for Ropsten and Mainnet will be hard-coded into this library. As a developer, you will simply need to pick the appropriate replay protection. \n\n\n### How to sign a meta-transaction \n\nA meta-transaction has the following parameters:\n\n- Signer: The Wallet of the signer\n- Target address: The address of the target contract\n- Value: Quantity of ether to transfer (only useful for contract accounts)\n- Calldata: Encoded function to call and the appropriate data\n\nTo sign a meta-transaction:\n\n```\nconst callData = targetContract.interface.functions.test.encode([]);\n\nconst params = await hubReplayProtection.signMetaTransaction(\n  signer,\n  targetContract.address,\n  new BigNumber(\"0\"),\n  callData\n);\n```\n\nA list of parameters is returned which can be used to send the transaction: \n\n```\ninterface ForwardParams {\n  hub: string; // Relay hub (or contract account) address \n  signer: string; // Signer's address\n  target: string; // Target contract address \n  value: string; // Value to send \n  data: string; // Calldata for target\n  replayProtection: string; // Encoded replay protection \n  replayProtectionAuthority: string; // Address of replay protection authority \n  chainId: number; // ChainID\n  signature: string; // Signer's signature\n}\n```\n\nTo send off the meta-transaction, the relayer just needs to execute forward: \n\n```\nconst tx = relayHub.connect(sender).forward(params.target, params.value, params.data, params.replayProtection, params.replayProtectionAuthority, params.signer, params.signature);\n```\n\nWhile the application is alive, the last replay protection used for the signer will be remembered. If the application restarts, it will fetch the last used values from the hub contract. \n\nOf course, be careful that there is a race condition if there is a restart while some meta-transactions are still in-flight. A future release may inspect the pending pool for the relevant data, but for 99% of cases it is not necessary. \n\n\n## How to build and test\n \nWe need to install the NPM packages:\n\n```\nnpm i\n```\n\nThen we can simply build and test:\n\n```\nnpm run build && npm run test\n```\n\n\n","readmeFilename":"README.md","gitHead":"5b84f9c91b4538cbc14d348214caf61895b67518","_id":"@anydotcrypto/metatransactions@0.0.3-2","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-fWQCQO+voucVoEq/Vc7GgStaQZUOyhisVuo62PgsIIP6sjBRDr2W366FWEe5cw6YkmGrOIfQK1vN+bK03IIItQ==","shasum":"703025c975e11d1779fc909d04cf992da513a5a2","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.3-2.tgz","fileCount":67,"unpackedSize":449713,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelMXWCRA9TVsSAnZWagAAgrAQAKIdT8HqTvWH86+quist\n7YxLPKDZBVXi1pW3yDiveiCuw26gK0QOoRdn44e4cGQInMrxQTqC/jBHqbgf\njAybZltHDbq5P61T1XvVIH2oEHL3pUPZIRvwXjBM0U2MIg/thwX0rmemV4s5\n3lOA7jTzZd+Vbux+z7tfgQlu5YTnmCklKhbT6j2mJFPGjgnl2z4zGiAN+uCZ\nJALw8KiO/kc40dkI9pEtdqRcyik0TG1J00c+E025+2bzEbEywV9h1fO4zZ5m\nnNMxSRJ2EuJ6eSkbCYlFzq8PwH4yLd+OouYBo0lWliYirh3BKuHRw3PEpicE\nh7JvnVEMmM8ABWVq5/zsETOuyOP1rk5z1oHDSSsFXQg5xCfdOdCpZDVWYS06\nhJLkTbM3L2pp8/YvKLXC+cJ1zcoXFraRKZyxqrgFYL/gkzzARxq5zSIqM55M\nzHe9RSXZTC9Hb+hho2TNOMgmU/q9UAJKnSW+hsugk9/SFzozwPn4smRjBJJX\nI5M5YiVXf8N197EJmtO+yWp6ZOOTySbWXPotQV8iYKXrXwnvoh/HwWd6R2fu\naopCWchdgy4mx/R0pCcNOW84yeC7wcKd5UXqrYROYLJtJhmszN4eiMkqqO2R\nXKbE7KXTI3Tmc04+ClMJADkhh/uPhSCMYw+k+cDT/dTrCz090S4/qXslHL6P\nhOm/\r\n=bCik\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEF6n7WNUpva3jrodSKW3R/lwFhLk3ScDrpsu2bJLDL4AiAjz8uvkzUr9vt+uGcFg/Qeo15TMx5X1W/cToPTDLZ7nA=="}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.3-2_1586808277639_0.43410131385724693"},"_hasShrinkwrap":false},"0.0.3-3":{"name":"@anydotcrypto/metatransactions","version":"0.0.3-3","description":"A minimal approach for meta-transaction support.","main":"dist/src/index.js","types":"dit/src/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts && tsc -p tsconfig.json && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/ts/deployment.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run runtest -- --timeout='30000'","prepublish":"rm -r ./dist && rm -r ./build && npm run build"},"devDependencies":{"@any-sender/client":"^0.2.0-beta.0","@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","bn.js":"^5.1.1","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","ethers":"^4.0.43","install":"^0.13.0","mocha":"^7.0.0","np":"^6.2.1","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"dependencies":{},"readme":"# A Minimal Relay Hub (motivated by EIP-2585).\n \nThe fundamental problem we are solving is that an Ethereum transaction intertwines the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is not straight forward for Alice to pay the gas fee on bealf of Bob who wants to execute a command in a smart contract.  \n\nGenerally, the motivating reason to solve this problem is to allow a third party (Alice) to offer transaction infrastructure as a service to others (bob) in a non-custodial manner. This is useful for wallet providers who can offer a better user-experience for customers while maintaining their self-custody and for most new projects who can plug-in an infura-like transaction API instead of re-building the infrastructure themselves. \n\nSo far, there are two prominent methods to solve the problem: \n- Contract accounts: Each user has a smart contract that forwards commands\n- \\_msgSender: Modify existing smart contracts to support accepting externally signed messages.\n\nThe problem, like all problems in Ethereum, is that there are several standard ways to implement it (roll-your-own proxy or roll-your-own permit). More often than not, existing solutions intertwine with the application and it is hard to generalise it. \n\nBut if we boil down the problem, what really needs to be solved is just replay protection for the meta-transaction. e.g. Is this the latest signed message by the user? And of course, has this signed message been seen before? \n\nOur goal is to provide a minimal forwarder that simply handles replay protection for the signer before forwarding the contract call: \n\n- Dual-solution: Support both contract accounts and \\_msgSender()\n- Client library: Provide a single client library for authorising a meta-transaction \n- Better-than-Ethereum Replay Protection: Experiment with more exciting repay protection to support concurrent and out-of-order transactions. \n\nOf course, this solution cannot help existing users who sign Ethereum transactions to authenticate via msg.sender for existing contracts. Going forward, it can help users who are willing to switch their identity to a contract account (msg.sender) or if contracts adopt the \\_msgSender() standard. \n \n \n## Replay Protection Hub\n\nWe have created a single class, RelayProtectionHub, that takes care of signing meta-transactions for the RelayHub / Contract Account. \n\nIt supports by default:\n- Replace by nonce (single queue)\n- Multinonce (multiple queues)\n- Bitflip \n\n### How to set up \n\nWe will cover how to set up the RelayHub as setting up a ContractHub is very similar.\n\nTo create your own relay hub: \n```\n  const relayHubFactory = new RelayHubFactory(admin);\n  const relayHubCreationTx = relayHubFactory.getDeployTransaction();\n  const relayHubCreation = await admin.sendTransaction(relayHubCreationTx);\n  const receipt = await relayHubCreation.wait(1);\n```\n\nTo connect to an existing relay hub: \n```\n  const relayHubAddress = \"0x0......\";\n  const relayHubFactory = new RelayHubFactory(admin);\n  const relayHub = relayHubFactory.attach(relayHubAddress);\n```\n\nTo set up the replay protection hub:\n\n```\n// Single queue \nconst hubReplayProtection = HubReplayProtection.multinonce(relayHub, 1);\n\n// Multi queue \nconst hubReplayProtection = HubReplayProtection.multinonce(relayHub, 10);\n\n// Bitflip\nconst hubReplayProtection = HubReplayProtection.bitFlip(relayHub);\n\n```\n\nIn the future, the RelayHub for Ropsten and Mainnet will be hard-coded into this library. As a developer, you will simply need to pick the appropriate replay protection. \n\n\n### How to sign a meta-transaction \n\nA meta-transaction has the following parameters:\n\n- Signer: The Wallet of the signer\n- Target address: The address of the target contract\n- Value: Quantity of ether to transfer (only useful for contract accounts)\n- Calldata: Encoded function to call and the appropriate data\n\nTo sign a meta-transaction:\n\n```\nconst callData = targetContract.interface.functions.test.encode([]);\n\nconst params = await hubReplayProtection.signMetaTransaction(\n  signer,\n  targetContract.address,\n  new BigNumber(\"0\"),\n  callData\n);\n```\n\nA list of parameters is returned which can be used to send the transaction: \n\n```\ninterface ForwardParams {\n  hub: string; // Relay hub (or contract account) address \n  signer: string; // Signer's address\n  target: string; // Target contract address \n  value: string; // Value to send \n  data: string; // Calldata for target\n  replayProtection: string; // Encoded replay protection \n  replayProtectionAuthority: string; // Address of replay protection authority \n  chainId: number; // ChainID\n  signature: string; // Signer's signature\n}\n```\n\nTo send off the meta-transaction, the relayer just needs to execute forward: \n\n```\nconst tx = relayHub.connect(sender).forward(params.target, params.value, params.data, params.replayProtection, params.replayProtectionAuthority, params.signer, params.signature);\n```\n\nWhile the application is alive, the last replay protection used for the signer will be remembered. If the application restarts, it will fetch the last used values from the hub contract. \n\nOf course, be careful that there is a race condition if there is a restart while some meta-transactions are still in-flight. A future release may inspect the pending pool for the relevant data, but for 99% of cases it is not necessary. \n\n\n## How to build and test\n \nWe need to install the NPM packages:\n\n```\nnpm i\n```\n\nThen we can simply build and test:\n\n```\nnpm run build && npm run test\n```\n\n\n","readmeFilename":"README.md","gitHead":"b19e1d108a0b459c50a24012fc63d12a68e8845a","_id":"@anydotcrypto/metatransactions@0.0.3-3","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-f8FgiHVaysOC9kbUjgXllCuhh3mM1P7Bw2GrkhQwsouorFsXRRpxnoqlQlHAm/QNSdxKU+fG0VXWl6iFCksFbQ==","shasum":"662a96bf2cb3027f073431fa45e0b0a3ba1a141f","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.3-3.tgz","fileCount":67,"unpackedSize":450283,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelMuoCRA9TVsSAnZWagAA35EP/1DqmQ9LL43dD25Vg3IX\ncThnGlnHTgmeiN8OY2Gqwv9HAIGh9RFbIDPsrKLK6Ch/4Gp3ZQOAkFg8rPV/\n6L2RLNCH73IKOr/pvmzCZX6/gRCAdZtfmsh10bH+3JiAmfwJiEkiQtndl/LL\nTPniQt74h8aguTZRRmJqLIwryOC/5AM7NY3RAZ2CP877fP6QJ0AKgBhY7qc6\nUjJq4KzrZigjvxh1xHMaAWT7WBqrt1GotySB58NiL+M0vKzAL4MSvG7CD9pR\ngM4m4ttgOXE/r9JnHT8BP7OpUkLWY2LeQ47g2b8a4BA8cAHjkWUwd4XJsHEk\nCU7A0pBLimvm0597qnnQBXA+m47tV0EkBS+VffPdWZzQ1qdczPXbk0B1D0io\nBpz6BkYT6E7eTtB15cMVEpCT70tJ2b3izJMOQmgAWG/gPJO18LUBgtLHn5iB\nHN7B/DBEUx7he3iXfRswU/yXEshy9AecqaQNNdasec115NjFR2xt4SmZspha\nIsQ2c5dI8MjGmHEcjkCWiDj4ujHhA9BgJDDIy1gGGbOTgPzxSbuxPY54Izy+\n3I2RIjgkSaI8AgQ0om3+8olbJXPv4j//thuDbxAMwFHGJHvB7eY3jjMoAUsp\n3CuxbdWbrUNVwcGfeilix6vRuHM89TBELsCvD6ni7RYwJfPk0EU2ocq8xP6c\nYQTP\r\n=iMW1\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC0h+B1cdCfYpceTE9OEPgk4LDFlptciD843Hc0DFQ3FQIgHlKz90dJ8gcK/4gzPWNQUyT2sw2qtDfoqMOJmVHvZ7g="}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.3-3_1586809767869_0.18364405590456045"},"_hasShrinkwrap":false},"0.0.3-4":{"name":"@anydotcrypto/metatransactions","version":"0.0.3-4","description":"A minimal approach for meta-transaction support.","main":"dist/src/index.js","types":"dit/src/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts && tsc -p tsconfig.json && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/ts/deployment.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run runtest -- --timeout='30000'","prepublish":"rm -r ./dist && rm -r ./build && npm run build"},"devDependencies":{"@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","np":"^6.2.1"},"dependencies":{"@any-sender/client":"^0.2.0-beta.0","@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5","ethers":"^4.0.43","bn.js":"^5.1.1","npm":"^6.14.4","ts-node":"^8.8.2"},"readme":"# A Minimal Relay Hub (motivated by EIP-2585).\n \nThe fundamental problem we are solving is that an Ethereum transaction intertwines the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is not straight forward for Alice to pay the gas fee on bealf of Bob who wants to execute a command in a smart contract.  \n\nGenerally, the motivating reason to solve this problem is to allow a third party (Alice) to offer transaction infrastructure as a service to others (bob) in a non-custodial manner. This is useful for wallet providers who can offer a better user-experience for customers while maintaining their self-custody and for most new projects who can plug-in an infura-like transaction API instead of re-building the infrastructure themselves. \n\nSo far, there are two prominent methods to solve the problem: \n- Contract accounts: Each user has a smart contract that forwards commands\n- \\_msgSender: Modify existing smart contracts to support accepting externally signed messages.\n\nThe problem, like all problems in Ethereum, is that there are several standard ways to implement it (roll-your-own proxy or roll-your-own permit). More often than not, existing solutions intertwine with the application and it is hard to generalise it. \n\nBut if we boil down the problem, what really needs to be solved is just replay protection for the meta-transaction. e.g. Is this the latest signed message by the user? And of course, has this signed message been seen before? \n\nOur goal is to provide a minimal forwarder that simply handles replay protection for the signer before forwarding the contract call: \n\n- Dual-solution: Support both contract accounts and \\_msgSender()\n- Client library: Provide a single client library for authorising a meta-transaction \n- Better-than-Ethereum Replay Protection: Experiment with more exciting repay protection to support concurrent and out-of-order transactions. \n\nOf course, this solution cannot help existing users who sign Ethereum transactions to authenticate via msg.sender for existing contracts. Going forward, it can help users who are willing to switch their identity to a contract account (msg.sender) or if contracts adopt the \\_msgSender() standard. \n \n \n## Replay Protection Hub\n\nWe have created a single class, RelayProtectionHub, that takes care of signing meta-transactions for the RelayHub / Contract Account. \n\nIt supports by default:\n- Replace by nonce (single queue)\n- Multinonce (multiple queues)\n- Bitflip \n\n### How to set up \n\nWe will cover how to set up the RelayHub as setting up a ContractHub is very similar.\n\nTo create your own relay hub: \n```\n  const relayHubFactory = new RelayHubFactory(admin);\n  const relayHubCreationTx = relayHubFactory.getDeployTransaction();\n  const relayHubCreation = await admin.sendTransaction(relayHubCreationTx);\n  const receipt = await relayHubCreation.wait(1);\n```\n\nTo connect to an existing relay hub: \n```\n  const relayHubAddress = \"0x0......\";\n  const relayHubFactory = new RelayHubFactory(admin);\n  const relayHub = relayHubFactory.attach(relayHubAddress);\n```\n\nTo set up the replay protection hub:\n\n```\n// Single queue \nconst hubReplayProtection = HubReplayProtection.multinonce(relayHub, 1);\n\n// Multi queue \nconst hubReplayProtection = HubReplayProtection.multinonce(relayHub, 10);\n\n// Bitflip\nconst hubReplayProtection = HubReplayProtection.bitFlip(relayHub);\n\n```\n\nIn the future, the RelayHub for Ropsten and Mainnet will be hard-coded into this library. As a developer, you will simply need to pick the appropriate replay protection. \n\n\n### How to sign a meta-transaction \n\nA meta-transaction has the following parameters:\n\n- Signer: The Wallet of the signer\n- Target address: The address of the target contract\n- Value: Quantity of ether to transfer (only useful for contract accounts)\n- Calldata: Encoded function to call and the appropriate data\n\nTo sign a meta-transaction:\n\n```\nconst callData = targetContract.interface.functions.test.encode([]);\n\nconst params = await hubReplayProtection.signMetaTransaction(\n  signer,\n  targetContract.address,\n  new BigNumber(\"0\"),\n  callData\n);\n```\n\nA list of parameters is returned which can be used to send the transaction: \n\n```\ninterface ForwardParams {\n  hub: string; // Relay hub (or contract account) address \n  signer: string; // Signer's address\n  target: string; // Target contract address \n  value: string; // Value to send \n  data: string; // Calldata for target\n  replayProtection: string; // Encoded replay protection \n  replayProtectionAuthority: string; // Address of replay protection authority \n  chainId: number; // ChainID\n  signature: string; // Signer's signature\n}\n```\n\nTo send off the meta-transaction, the relayer just needs to execute forward: \n\n```\nconst tx = relayHub.connect(sender).forward(params.target, params.value, params.data, params.replayProtection, params.replayProtectionAuthority, params.signer, params.signature);\n```\n\nWhile the application is alive, the last replay protection used for the signer will be remembered. If the application restarts, it will fetch the last used values from the hub contract. \n\nOf course, be careful that there is a race condition if there is a restart while some meta-transactions are still in-flight. A future release may inspect the pending pool for the relevant data, but for 99% of cases it is not necessary. \n\n\n## How to build and test\n \nWe need to install the NPM packages:\n\n```\nnpm i\n```\n\nThen we can simply build and test:\n\n```\nnpm run build && npm run test\n```\n\n\n","readmeFilename":"README.md","gitHead":"5a1706861859081448575c9d73db3f36109a4af0","_id":"@anydotcrypto/metatransactions@0.0.3-4","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-rG+ChLoFQVgzmkY6Qjr8+c6Cox9y11GSiwTGvQE8zQYTTLFZwQ3DS9e0PPv8PQrejsxu3TiZwOHpA3ija75Jjg==","shasum":"21053d388cbc639433d351f9749decd09230b0bc","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.3-4.tgz","fileCount":67,"unpackedSize":450259,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelM/0CRA9TVsSAnZWagAAkT0P/297/ngsJhFgDdspvhHJ\nEKmDrodhFmCPz8gtBIsLwdHZecxFk+MaYQ8BAPxH9CSPE5+WgB2GAAyqvDtz\nPVwxHXw0SVF71I2gJk03gHzEcvalI82P8OCHkVzkiVFu7Slb5grN8YgCTqWp\n/b/rzUNJnM1KOVgoJCmc4IBzbxyJrAqTMtISfDQylCxOfMXNF93wIGwsXpRa\nwuDo7EBs2EInCJGO/U58tSlw1Nki14aQazCMnxjHh9PWuWKSZEFPOiXFSc2H\nrSma8dyo0J+EOUyi7c5knJguxAzd8k9W0i+92XFgeF+UqyzcJHM8yx/aEuwZ\nlheq4xaMJ7Niyt+lpZWI1x4Q/OFImQ57QwQf2dWLtiWA/+Y1ImXzFxZsYUzD\naUTGvLulpfSf1521GWYUNSQzCerZxLNnfx4/ScHK2BHJXuqd5pRp9Q5hqlk5\nlybARf95/G7sIQ345WLy6YE4ecO4trVIwZpxYK9+kqrG0Pv0Ps3qft05QNKO\nzbXws9N2sGkoj4Dk7QWrU6KZsX5wur89tmOuZCwvjnVJbUEg2Inkkua299JR\npsh1TWWZ3lvZcZr4lQdm4S8cWcBTY4P4XTD8MBTFxS6CUy1yYCaTXB94a9zA\njG5FZnmTi7liIAGXNvpHM6cfsvi/22gqYyt5eXdTnNQlpmkKaZr0d4FCdh+o\nmS7R\r\n=ebDo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIByK/0ai2D30Gy9OEafHUkECeU5X5O9GnpEBl3mvWrG9AiEA6q5C6THMc5zYQfk84EULofhwwG6ko/EcTkMRAV0XKtE="}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.3-4_1586810867930_0.13332802307508396"},"_hasShrinkwrap":false},"0.0.3":{"name":"@anydotcrypto/metatransactions","version":"0.0.3","description":"A minimal approach for meta-transaction support.","main":"dist/src/index.js","types":"dit/src/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts && tsc -p tsconfig.json && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run runtest -- --timeout='30000'","prepublish":"rm -r ./dist && rm -r ./build && npm run build"},"devDependencies":{"@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","np":"^6.2.1"},"dependencies":{"@any-sender/client":"^0.2.0-beta.0","@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5","ethers":"^4.0.43","bn.js":"^5.1.1","npm":"^6.14.4","ts-node":"^8.8.2"},"gitHead":"a8ad8572dffc9db8e9e3f8fb960068bd4778847c","_id":"@anydotcrypto/metatransactions@0.0.3","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-PFOmba5C6IWa6wydJfy5RE75szB20pvPe20a+z2heKxONuGPgYsQjw86DI1V2yXFjGRC83Ts/IVKIWObNezooA==","shasum":"8aa447462a799a5928852c18a43d3c312bb4c81e","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.3.tgz","fileCount":70,"unpackedSize":476643,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJele3eCRA9TVsSAnZWagAAqC8P/3oDnTxs0GndoklYO3gQ\nxLT1sSZhZ4UGN5alCO06B6guL7itWzAPKBPhZdxn6cliq26NzsKV5LknC5Pb\nLKgnTPDAwF6IiNq+dDsKmp2qvOFyCWjvVhtT1v7NUQFGYt6DYakEhQrhqZQK\nGj39Tj2TNBf/Gn1Yie+u40ehpitHi6ntCu3niyaWUUdXFNB1XjVA1rex1laj\nnem4++JssbuTxUG6CcopoeGnuJsklvgWYXPCxBp9P8E06+AmfkgEN+2INLj6\nVRSu4TdzIq2TTI8LK94DBDB2ZBZ/VXYungNHtw6ls/OQQbExnZWtz2CKkw8Z\nwd1F5BjtEzcytoilCqHxdgafuFUMLua6RhrlUiodKKVr3Qu5W1pNtfg+Nz/O\nJLOyHRU5y1x7c1YW/3JjwUpOtHLkLGWvi++EDNxsdXEW8qOI0B4dVg5ARiNa\nj5RV1Wq5GR3ozC1fNjb8Ksz9PEL/51MCOIrfCHS2UxIJMFkQM9Y+C+vYa9It\nA6kUX9l3alcAkF23qFJSP5FDlXHwqPQsbfyC7wC48m5oKXSTKedr/PPixZSX\niqfsczJsf84dxml+Na2Tlpc6MowuJg0jILqN/Xzea0td85Rs1sz+XCNYyJMe\n2jxpcW8yL4NbhmG5ygkBjROSOE7A0VpYNTIIACYVs0Agpbi4SLDuTyk+3cRI\nDOUh\r\n=XClx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCrrXsiXkKEy6Rh/F/I307UvEDPy/hqjkxOmdmvtL4voAIhALzGp+0AP8RKCM1gNYtzKQ3DI4w/4r8CNz5LlCe4oJjj"}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.3_1586884061551_0.7171105809935618"},"_hasShrinkwrap":false},"0.0.4":{"name":"@anydotcrypto/metatransactions","version":"0.0.4","description":"A minimal approach for meta-transaction support.","main":"dist/src/index.js","types":"dit/src/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts && tsc -p tsconfig.json && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run runtest -- --timeout='30000'","prepublish":"rm -r ./dist && rm -r ./build && npm run build"},"devDependencies":{"@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","np":"^6.2.1"},"dependencies":{"@any-sender/client":"^0.2.0-beta.0","@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5","ethers":"^4.0.43","bn.js":"^5.1.1","npm":"^6.14.4","ts-node":"^8.8.2"},"gitHead":"78de09f8c204a057cb3797a4365e416b0b909e81","_id":"@anydotcrypto/metatransactions@0.0.4","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-t8hD5/tR2MjAoakWasupTH8EQ/sgib8I2kWWBQNmYVSCCIVjKg2zRd4U3X6vVj0d0LAB+OkpdZdvN3gYqqosUg==","shasum":"8e8f8bc09ea5abc965d6213d7afec62ae1bab7fb","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.4.tgz","fileCount":70,"unpackedSize":477458,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelfX4CRA9TVsSAnZWagAA4IcP/0TYtd9hISMyuxUVtdyW\nWavrSt5QJGSJD4wvujThXLfBC27Es6l4NIjPaMYpKHqvYwZNnT9zly+7Lpa1\nqHf4aQeUykdDeDznk9By0HtWea5oRsnJxU0oAniifIVj5FtYd4ifKJ6Fx/jK\n7C2kYf904m6MzHpGrM56CvXYOeJOM4PPPvr8jdP5BAUJ+GKH5DwX9Fg99toK\nmgtqNsNHgdNCBDgxata679yFxr8VxsHS71Z9h1n2wMIVAC3vIdLHZp40jzB7\n3Qq7PLctRSi3sip/YbKaHw8Hnsf5Gwo9AQK1JsEN2HQldZd/enMmy8tyWvWw\nKeC8jVi7Lr21RSvXrSUuuB2L1j6zt1PZE5eBbi6LEgT8F+XIkcy9uGJFylFK\nZmpLM2q2ICou7tsqvfvLi8qUxSKiXshtwee2XxG3KC+RhHLE8+AGgpQrMNb8\nhOgfgOHHoCe1o4rAaDU4ccRUrfpH6znih2yHjC08MnX1iY4QRM/0/hN2xB9Z\nVtN8H9mbJLjN5QV9jOTYlmWTQhFrIXu1VRmBirseW4ykxrDApZ4KVASbfwAx\nnrnZohen1CE1M8CzBc8evBTfmQG4e5lwGFU0AioJmZBVSt/xYXgEKmCxctNu\npzjrq1FZNeD+9ewMSXGAqwLfFyp759okWaTpQTzvyP0CpljaSKYxiOlTG5hk\nyzaZ\r\n=1lFI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCUvl3VBG6lvjypHUGi91vc4uOOeSrvW1l1xpYkbm4EoAIgfck0Kue5qzqullox4NsaGKI9TaQ3cQBVgNMQVvq0O24="}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.4_1586886135749_0.053109037602792286"},"_hasShrinkwrap":false},"0.0.5":{"name":"@anydotcrypto/metatransactions","version":"0.0.5","description":"A minimal approach for meta-transaction support.","main":"dist/src/index.js","types":"dit/src/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts && tsc -p tsconfig.json && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run runtest -- --timeout='30000'","prepublish":"rm -r ./dist && rm -r ./build && npm run build"},"devDependencies":{"@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","np":"^6.2.1"},"dependencies":{"@any-sender/client":"^0.2.0-beta.0","@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5","ethers":"^4.0.43","bn.js":"^5.1.1","npm":"^6.14.4","ts-node":"^8.8.2"},"gitHead":"2f3912b5bed7d8d4eb1987b52a65cf0213e4ed3b","_id":"@anydotcrypto/metatransactions@0.0.5","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-TSZWgcW+gm2opKx/iBE0wsJoGjadpm8cEqdeDPeBNf1tJNeiRXvL30IxxQmAqLKQAQG+UN4THB6YbdlI/kC5Sg==","shasum":"93e50fc73559384d5c817e2c7c58cfe67ed2020a","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.5.tgz","fileCount":70,"unpackedSize":478087,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJemIU4CRA9TVsSAnZWagAAX28P/RoNqENNQpG79wHp9Y/k\n+ztaI/tkw6pIcy9DCDEoheDK8KZ1ZhTpBuSbjCIgXNudZbgHXmv1A904fNH6\nrWtsW48jeXvjAqyLdwTjU0TekibfhZUkAJyFyMkwngLoLMRNOUySOa6Be5HB\n1zZ7VYjb9qd1v+Ig5KKjhy+/pZgkmzYsbq60Nf1tyKGCQ7N4wtAOKrqcQ/+0\nx0JluYwAkWH/1a83QV0R12IX5bQwOLPteUV9Wr17V0gvKl+UQq6a+VYJIP7J\nWqx78gPkcTBVd/eDnDeTYmtr3gHAfgZEiWvYB1MmwjFPgC7uHHoh7r2XaMjR\no6Xuw9jcUZNaW5rTSED58MY/OaYh7LEd0c6oQIPYV/XSryX7dM+l7AqHTjoQ\n4ECcCX9I2Ztb/WT7xNPrT5ze83vqVkpM6tI0s9U2TFf+/gpu9TE+7dSSJeRA\npdK6Rwtu+HZVBQceDp9t371C3MDJ8fDxhtV+ZBMPIi83AeSIBkJk/0e6wLiD\n0xDJZfwPhh6N5mFb9H6Yxdj8vCtidXzXCJucY8ihqK1ieEC/Sx31vG0tN4pv\nB6LsJKt1bdeqGbCETtSmtUfc1sTSsInvlOBnwVsZqLjQ5sUBfHRXQqX+aV8Y\nLAq5JROba6zcSlLa71L8V4v5/R3xBifXBMs90I1LW8MUd8U4u9pybAmlxIOy\nIBZX\r\n=0wWO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGfSJ15d5ybj8bhZVOmcdXS2u0O/uYslsN8yC0uc56VEAiB3xsi8CwV2ee5Ld5zxxrRF3z17a/9a8/vT8HxqVDZATg=="}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.5_1587053879907_0.2114136304499583"},"_hasShrinkwrap":false},"0.0.6":{"name":"@anydotcrypto/metatransactions","version":"0.0.6","description":"A minimal approach for meta-transaction support.","main":"dist/src/index.js","types":"dit/src/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts && tsc -p tsconfig.json && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run runtest -- --timeout='30000'","prepublish":"rm -r ./dist && rm -r ./build && npm run build"},"devDependencies":{"@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","np":"^6.2.1"},"dependencies":{"@any-sender/client":"^0.2.0-beta.0","@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5","ethers":"^4.0.43","bn.js":"^5.1.1","npm":"^6.14.4","ts-node":"^8.8.2"},"gitHead":"de61a0834a98ba3fe5f11bce67d3fff4720c4469","_id":"@anydotcrypto/metatransactions@0.0.6","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-DrK9wgBqWNwH6xUrwnqVJM352GxU+HelJH8mLipWJiKYSmfKGWOiSnEDUO1mbND98y80CrYV2IWETPnC0xoFBQ==","shasum":"a0fe892b75a8ca928e4668060d4a36afd3df6079","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.6.tgz","fileCount":70,"unpackedSize":479119,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJemI0UCRA9TVsSAnZWagAAxGUP/183BjKbIQB6owa+g8mZ\nuzi1yXJJ/KYFOVU57MOlvJmmdNY2gWVf4qv7h99fd5JZfy2UojxGRUFC/hWP\nNVY74jlE+BW3yyFP/AEjiyO8ndnLV30rKhQsXvySr5hcVuFWkq3wZqjYYAHk\nzhddHhivQu6S2rqR1gP0o4T8g2UxGrJBoiInqVjndyt1O0KNuwq2y+krMZmO\nWZyzYMcGeRpl7vOjaTasn4tjRyA9dXvkbpSgrQAVo9zbWoMzTTR7eg15WWCw\neM1WJ2AAnVY7qJjpt99r5349Mj3KZUshSWs55wwLguKlIvlKfIRabXp9c5/+\nMSNJZ/u1N8U9gNHcFKPXU231CSdnXRMUsnsj+MS4eKxrChburEUGPbMvdOfY\nnO6jKnpaZqQFR+dsWS2FxaW/1pB5PbMotxFXLNjqYgSe428FYOUOjwSqL1jb\nZyhBB46C/sEQc1dePeHKPz8y3OjAlu6NwcevM3fCStjOXRWqjGZOswGLzKBk\nztvWEv9aHmggwEM5L3LAe6jCmZcpB+PX2gn76U9LMgh7oioyZsI+jw3EgT5W\nPPk0GdXAfbUXzhtmp8ZmlriZn1TDZph60GOVq5AUuMaY/rXLuhccGukrKHUG\nNGUpgmt+NcakR1ihRlwD/HRmz+VdPn2Z88wafP1cL03Ipt41KXkJ3MYizWdL\ncghl\r\n=rRk+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICAgi4wsXVew3URb3Ct1Kk1oTJAXD7QYAmpsNGlKoIfIAiEAokQ/9lDuQib5RmIgcTGwrL6blaVK3wNhOI8ItS7OjlA="}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.6_1587055891594_0.5311523820168129"},"_hasShrinkwrap":false},"0.0.7-0":{"name":"@anydotcrypto/metatransactions","version":"0.0.7-0","description":"A minimal approach for meta-transaction support.","main":"dist/src/index.js","types":"dit/src/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts && tsc -p tsconfig.json && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run runtest -- --timeout='30000'","prepublish":"rm -r ./dist && rm -r ./build && npm run build"},"devDependencies":{"@pisa-research/utils":"^0.1.39","@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","np":"^6.2.1"},"dependencies":{"@any-sender/client":"^0.2.0-beta.0","@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5","ethers":"^4.0.43","bn.js":"^5.1.1","npm":"^6.14.4","ts-node":"^8.8.2"},"readme":"# A Minimal Relay Hub (motivated by EIP-2585).\n \nThe fundamental problem we are solving is that an Ethereum transaction intertwines the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is not straight forward for Alice to pay the gas fee on bealf of Bob who wants to execute a command in a smart contract.  \n\nGenerally, the motivating reason to solve this problem is to allow a third party (Alice) to offer transaction infrastructure as a service to others (bob) in a non-custodial manner. This is useful for wallet providers who can offer a better user-experience for customers while maintaining their self-custody and for most new projects who can plug-in an infura-like transaction API instead of re-building the infrastructure themselves. \n\nSo far, there are two prominent methods to solve the problem: \n- Contract accounts: Each user has a smart contract that forwards commands\n- \\_msgSender: Modify existing smart contracts to support accepting externally signed messages.\n\nThe problem, like all problems in Ethereum, is that there are several standard ways to implement it (roll-your-own proxy or roll-your-own permit). More often than not, existing solutions intertwine with the application and it is hard to generalise it. \n\nBut if we boil down the problem, what really needs to be solved is just replay protection for the meta-transaction. e.g. Is this the latest signed message by the user? And of course, has this signed message been seen before? \n\nOur goal is to provide a minimal forwarder that simply handles replay protection for the signer before forwarding the contract call: \n\n- Dual-solution: Support both contract accounts and \\_msgSender()\n- Client library: Provide a single client library for authorising a meta-transaction \n- Better-than-Ethereum Replay Protection: Experiment with more exciting repay protection to support concurrent and out-of-order transactions. \n\nOf course, this solution cannot help existing users who sign Ethereum transactions to authenticate via msg.sender for existing contracts. Going forward, it can help users who are willing to switch their identity to a contract account (msg.sender) or if contracts adopt the \\_msgSender() standard. \n \n \n## Replay Protection Hub\n\nWe have created a single class, RelayProtectionHub, that takes care of signing meta-transactions for the RelayHub / Contract Account. \n\nIt supports by default:\n- Replace by nonce (single queue)\n- Multinonce (multiple queues)\n- Bitflip \n\n### How to set up \n\nWe will cover how to set up the RelayHub as setting up a ContractHub is very similar.\n\nTo create your own relay hub: \n```\n  const relayHubFactory = new RelayHubFactory(admin);\n  const relayHubCreationTx = relayHubFactory.getDeployTransaction();\n  const relayHubCreation = await admin.sendTransaction(relayHubCreationTx);\n  const receipt = await relayHubCreation.wait(1);\n```\n\nTo connect to an existing relay hub: \n```\n  const relayHubAddress = \"0x0......\";\n  const relayHubFactory = new RelayHubFactory(admin);\n  const relayHub = relayHubFactory.attach(relayHubAddress);\n```\n\nTo set up the replay protection hub:\n\n```\n// Single queue \nconst hubReplayProtection = HubReplayProtection.multinonce(relayHub, 1);\n\n// Multi queue \nconst hubReplayProtection = HubReplayProtection.multinonce(relayHub, 10);\n\n// Bitflip\nconst hubReplayProtection = HubReplayProtection.bitFlip(relayHub);\n\n```\n\nIn the future, the RelayHub for Ropsten and Mainnet will be hard-coded into this library. As a developer, you will simply need to pick the appropriate replay protection. \n\n\n### How to sign a meta-transaction \n\nA meta-transaction has the following parameters:\n\n- Signer: The Wallet of the signer\n- Target address: The address of the target contract\n- Value: Quantity of ether to transfer (only useful for contract accounts)\n- Calldata: Encoded function to call and the appropriate data\n\nTo sign a meta-transaction:\n\n```\nconst callData = targetContract.interface.functions.test.encode([]);\n\nconst params = await hubReplayProtection.signMetaTransaction(\n  signer,\n  targetContract.address,\n  new BigNumber(\"0\"),\n  callData\n);\n```\n\nA list of parameters is returned which can be used to send the transaction: \n\n```\ninterface ForwardParams {\n  hub: string; // Relay hub (or contract account) address \n  signer: string; // Signer's address\n  target: string; // Target contract address \n  value: string; // Value to send \n  data: string; // Calldata for target\n  replayProtection: string; // Encoded replay protection \n  replayProtectionAuthority: string; // Address of replay protection authority \n  chainId: number; // ChainID\n  signature: string; // Signer's signature\n}\n```\n\nTo send off the meta-transaction, the relayer just needs to execute forward: \n\n```\nconst tx = relayHub.connect(sender).forward(params.target, params.value, params.data, params.replayProtection, params.replayProtectionAuthority, params.signer, params.signature);\n```\n\nWhile the application is alive, the last replay protection used for the signer will be remembered. If the application restarts, it will fetch the last used values from the hub contract. \n\nOf course, be careful that there is a race condition if there is a restart while some meta-transactions are still in-flight. A future release may inspect the pending pool for the relevant data, but for 99% of cases it is not necessary. \n\n\n## How to build and test\n \nWe need to install the NPM packages:\n\n```\nnpm i\n```\n\nThen we can simply build and test:\n\n```\nnpm run build && npm run test\n```\n\n\n","readmeFilename":"README.md","gitHead":"9d3a193c49dbd62150f187bfd341b7f2a2299b5c","_id":"@anydotcrypto/metatransactions@0.0.7-0","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-VqG6F+LqT/xgr7KpGdvfw/UMyRB59ebTMJP7OhCwjRE0G9X45B5cIjiR2TWNzms5+2eJbvcseH91km49Uwr0ww==","shasum":"62d2ae1338b4f617c038aeea02fc111043de9334","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.7-0.tgz","fileCount":70,"unpackedSize":480046,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJen0zmCRA9TVsSAnZWagAApCAQAJI2AaXEzmFX7vba+5yV\n47PW6GIh+wsD7yCQ6M3dYZSmVSjcmuGCWMRPFvMqraO9CFMPPRfVlxE2A/p5\nDbVcRv+oLw7oc8z11QhYSsGlmGep9foRfOdNiONWbwgJWiPIh0ke0QxS8obE\ncIY+f85o5lLmPdZLimd5y8JsxkFcq0IGv8JYbHmewi8IQxmA0XWzdGBhe+Y/\nNANhQcSl13g3li+mMVj9oeelGUInoHJy6WLetOzvK94qMLmQFlMxwxhx5oLA\nQ3+CZWZbckM1N4qdd8mly48eMdceJQhn7Lhfd5f89Sda7a3CstNLqC/UWF7R\nhv5sHJfwh84BSwFcHjHhuZr4Zg4Gds4vGX/7350y3+VH0pxlnr23LvguVShl\nM23Z5ehcKVAGZF+RWjqBbzHWGypnkf2/4Lerh8LiZhe2YuzBJ9V+5kMJdiSn\nqg9BHQzm0BjZusXY6NXjQk2QtyiLEpyoCiiUMwrjke7/jD1upbA2De5na0VS\n6GEJOKw45wTFAPgSNgy4WOJWmug+jilMu3MJsQ/hTg9c1EvZYkTrtyjAWp7i\nrfT2AW46mRp5i9YuJ91KbSpuvnQvndgApIH14jhdMeftAVICOqACwogxRJOf\nqeC+3wKD8QJEKz5DAW1UxeXVPbcIfk6H0rloNA7eCPuUUSfiMNX8+IW5N1+C\nbJBS\r\n=VuGL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD8EnvBRBkTlrYReDV99ipKcpK2DtZdw8QU9/CTowEL0wIhANSp2phlmy065/kvCAylkbINsH+4M5qcx6j6COFUzzPG"}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.7-0_1587498214298_0.5219444175999972"},"_hasShrinkwrap":false},"0.0.7-1":{"name":"@anydotcrypto/metatransactions","version":"0.0.7-1","description":"A minimal approach for meta-transaction support.","main":"dist/src/index.js","types":"dit/src/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts && tsc -p tsconfig.json && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run runtest -- --timeout='30000'","prepublish":"rm -r ./dist && rm -r ./build && npm run build"},"devDependencies":{"@pisa-research/utils":"^0.1.39","@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","np":"^6.2.1"},"dependencies":{"@any-sender/client":"^0.2.0-beta.0","@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5","ethers":"^4.0.43","bn.js":"^5.1.1","npm":"^6.14.4","ts-node":"^8.8.2"},"readme":"# A Minimal Relay Hub (motivated by EIP-2585).\n \nThe fundamental problem we are solving is that an Ethereum transaction intertwines the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is not straight forward for Alice to pay the gas fee on bealf of Bob who wants to execute a command in a smart contract.  \n\nGenerally, the motivating reason to solve this problem is to allow a third party (Alice) to offer transaction infrastructure as a service to others (bob) in a non-custodial manner. This is useful for wallet providers who can offer a better user-experience for customers while maintaining their self-custody and for most new projects who can plug-in an infura-like transaction API instead of re-building the infrastructure themselves. \n\nSo far, there are two prominent methods to solve the problem: \n- Contract accounts: Each user has a smart contract that forwards commands\n- \\_msgSender: Modify existing smart contracts to support accepting externally signed messages.\n\nThe problem, like all problems in Ethereum, is that there are several standard ways to implement it (roll-your-own proxy or roll-your-own permit). More often than not, existing solutions intertwine with the application and it is hard to generalise it. \n\nBut if we boil down the problem, what really needs to be solved is just replay protection for the meta-transaction. e.g. Is this the latest signed message by the user? And of course, has this signed message been seen before? \n\nOur goal is to provide a minimal forwarder that simply handles replay protection for the signer before forwarding the contract call: \n\n- Dual-solution: Support both contract accounts and \\_msgSender()\n- Client library: Provide a single client library for authorising a meta-transaction \n- Better-than-Ethereum Replay Protection: Experiment with more exciting repay protection to support concurrent and out-of-order transactions. \n\nOf course, this solution cannot help existing users who sign Ethereum transactions to authenticate via msg.sender for existing contracts. Going forward, it can help users who are willing to switch their identity to a contract account (msg.sender) or if contracts adopt the \\_msgSender() standard. \n \n \n## Replay Protection Hub\n\nWe have created a single class, RelayProtectionHub, that takes care of signing meta-transactions for the RelayHub / Contract Account. \n\nIt supports by default:\n- Replace by nonce (single queue)\n- Multinonce (multiple queues)\n- Bitflip \n\n### How to set up \n\nWe will cover how to set up the RelayHub as setting up a ContractHub is very similar.\n\nTo create your own relay hub: \n```\n  const relayHubFactory = new RelayHubFactory(admin);\n  const relayHubCreationTx = relayHubFactory.getDeployTransaction();\n  const relayHubCreation = await admin.sendTransaction(relayHubCreationTx);\n  const receipt = await relayHubCreation.wait(1);\n```\n\nTo connect to an existing relay hub: \n```\n  const relayHubAddress = \"0x0......\";\n  const relayHubFactory = new RelayHubFactory(admin);\n  const relayHub = relayHubFactory.attach(relayHubAddress);\n```\n\nTo set up the replay protection hub:\n\n```\n// Single queue \nconst hubReplayProtection = HubReplayProtection.multinonce(relayHub, 1);\n\n// Multi queue \nconst hubReplayProtection = HubReplayProtection.multinonce(relayHub, 10);\n\n// Bitflip\nconst hubReplayProtection = HubReplayProtection.bitFlip(relayHub);\n\n```\n\nIn the future, the RelayHub for Ropsten and Mainnet will be hard-coded into this library. As a developer, you will simply need to pick the appropriate replay protection. \n\n\n### How to sign a meta-transaction \n\nA meta-transaction has the following parameters:\n\n- Signer: The Wallet of the signer\n- Target address: The address of the target contract\n- Value: Quantity of ether to transfer (only useful for contract accounts)\n- Calldata: Encoded function to call and the appropriate data\n\nTo sign a meta-transaction:\n\n```\nconst callData = targetContract.interface.functions.test.encode([]);\n\nconst params = await hubReplayProtection.signMetaTransaction(\n  signer,\n  targetContract.address,\n  new BigNumber(\"0\"),\n  callData\n);\n```\n\nA list of parameters is returned which can be used to send the transaction: \n\n```\ninterface ForwardParams {\n  hub: string; // Relay hub (or contract account) address \n  signer: string; // Signer's address\n  target: string; // Target contract address \n  value: string; // Value to send \n  data: string; // Calldata for target\n  replayProtection: string; // Encoded replay protection \n  replayProtectionAuthority: string; // Address of replay protection authority \n  chainId: number; // ChainID\n  signature: string; // Signer's signature\n}\n```\n\nTo send off the meta-transaction, the relayer just needs to execute forward: \n\n```\nconst tx = relayHub.connect(sender).forward(params.target, params.value, params.data, params.replayProtection, params.replayProtectionAuthority, params.signer, params.signature);\n```\n\nWhile the application is alive, the last replay protection used for the signer will be remembered. If the application restarts, it will fetch the last used values from the hub contract. \n\nOf course, be careful that there is a race condition if there is a restart while some meta-transactions are still in-flight. A future release may inspect the pending pool for the relevant data, but for 99% of cases it is not necessary. \n\n\n## How to build and test\n \nWe need to install the NPM packages:\n\n```\nnpm i\n```\n\nThen we can simply build and test:\n\n```\nnpm run build && npm run test\n```\n\n\n","readmeFilename":"README.md","gitHead":"77b295ba707a3f2d4e52b35cec0b19d21b47d700","_id":"@anydotcrypto/metatransactions@0.0.7-1","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-h3RT4iaht8ImpRFZRg1WF1Jdns6GCu0n09EdddDyHAEj0R9f9mLQWIWft8gMvpObInoPPOfS4HTvQK/zoyMGFw==","shasum":"5e953d551d428b9f03ec5edf1d9cfff086de855a","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.7-1.tgz","fileCount":70,"unpackedSize":480057,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJen1PKCRA9TVsSAnZWagAA/mMP/i+/Jv5VJDIvcy4WUUtO\nzluKT5BzqrqgYWVelYJUlOwRWwHa06KuYvAzIt7APDUNj4ITYrWMscCyhFZP\nwQuNbTTU/Nv5lNbP8J1uU8GH1++2gmo/6DoD8XkYhGxpUVDJ04ci2j+TQo2A\nld/Uf1CrQTy24msddXMYffX7ZyTs1rOM7+hH3+4tZbzYm/7impkGMUcWEdGm\nQOy9QoSnfrRXTXIZJYCVhKlRS9dzV1lGm4Fn/QltVpHVTvoiidlCa6oBbx7T\nK5oxhaKjzkgJfE6TE34avs/yxG2Jz8XSvbXBYtfGlWUhf7jvHcX+7iNmKHP1\n7blFRYXSaMfUAlBZaOy0IvugMNRvOCoTDautPNxZVrtNRjUWoQmlfZAQWGJ3\nacHepXd6SFJ2C/ryAbRFZsoUTobVK2ibz4nCUJHXLyOXhN6FquluBOBCI41P\nlGCJb2zxPu7pvf7ptQKpCZBPU1aztC7jbepixXTyCGfxwb0G+f5z7LXj3NAY\nqjYuc0+oFLBMbEvBkvAZnBYwyhigzpPNEdtrhRgvaDmjpt1AGSQtUr5ClOs5\nr3baYCRwz/787z0fBHHDDRiN5AHFYIOptYGXU+ppdFTgt0NXvGNH6/O3TV0g\nQLe9qevPR49uthryKFBzFHRgPpsUl29IQyAvKlhW6qEo8ln6Roxu2VtJ8ITy\n8M4w\r\n=ivOT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD6oG5ivrjOtD9d2e7eWHY4k+8vsyNT4Y3A+7Mkr64kBwIgKQhprSf0MVu76eak60zz/mbzWz3uwIaa2kLEo7rC9Tc="}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.7-1_1587499977990_0.4287779665636331"},"_hasShrinkwrap":false},"0.0.7":{"name":"@anydotcrypto/metatransactions","version":"0.0.7","description":"A minimal approach for meta-transaction support.","main":"dist/src/index.js","types":"dit/src/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts && tsc -p tsconfig.json && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run runtest -- --timeout='30000'","prepublish":"rm -r ./dist && rm -r ./build && npm run build"},"devDependencies":{"@pisa-research/utils":"^0.1.39","@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","np":"^6.2.1"},"dependencies":{"@any-sender/client":"^0.2.0-beta.0","@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5","ethers":"^4.0.43","bn.js":"^5.1.1","npm":"^6.14.4","ts-node":"^8.8.2"},"gitHead":"32e8a61338826749cdd7a1aac3f481f5fc8e32ed","_id":"@anydotcrypto/metatransactions@0.0.7","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-zVNfZt3r94swXG14aUYEq2xQQNDsKsmSJWwLD//5LqNOqdFpDvx4Svhs1ol72OU/QIUxQoqpZWTp5/awzzPmLw==","shasum":"ccf397156b32bf7e21951155f8493e69dc8f80f5","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.7.tgz","fileCount":70,"unpackedSize":480055,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJen1bhCRA9TVsSAnZWagAAApIP/AppxtI7ZYqI8m+frFCe\nCUSehVZXOGv6H6zghy6RRXxyk6nFt/7lhMEKoV9zxReau4h4hiMRYlaKpEvg\nzMz0hBnEI/GniSgM56+xyNf6gPuOC7NAyQsQAmXG3xYPqX3gG4FiTNhcVRKS\n4fe+Df+Y+lJhIgtiboNiCLCf5ps4EP3VCaVyTB8uAQWfa6Zz/29s5iloWm6u\ndKhxzggpn0jSY5WHDMY7PDjttFx/X9eS5IdDqnxZDfK7u5vE6tYNuwn9iuIm\nKNfTdtTdQjvNhtNVr0DzefAXtAf4VNz/OI+n4CkMSLzS1LcSq0PWnllv2xcb\nWkWZqKGA4nEUTLYWL8IP+U7MbkICvy5KGW1xpX+8epnnDttvmFxLIKTYgO0L\nAFQDmzRGN+5KmZ3BV06UzDz1h1J1Qwx8GZ2bQcpHVRqfpVhnLaqokSQy2JZ9\ndA7jlfW+qXsgA9ezJq3EmNB5tzpSYSeO742c3D2aTAPxTq0M4pVYj2LfqDWq\nWDQHyc8/P58Rr/porK9pEVIDst4pZmvEy37Rb5wusDBjKUg25Gemz/vBfbmw\ndg4U3SUfwt/fLsDYPFhfOM7FoufK8R4gxIcmTlT/TU+hkwDl0orrD5aE50Kl\n7i5Gt2KMhZlgwfDHHPdXjlvYsWWyNGQr9+CMVOirfOkgVmnEclfXNTTxtcfJ\nYrlq\r\n=8WlL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEwht5DnOzzPmyjC6LaShRZsC7ED082qGtVVQQwc5uN1AiBr0SM5Xc10sajOQ88uo0odzZlggKx20HHMsasH9V9u8w=="}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.7_1587500768729_0.7111080860411512"},"_hasShrinkwrap":false},"0.0.8":{"name":"@anydotcrypto/metatransactions","version":"0.0.8","description":"A minimal approach for meta-transaction support.","main":"dist/src/index.js","types":"dit/src/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts && tsc -p tsconfig.json && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run runtest -- --timeout='30000'","prepublish":"rm -r ./dist && rm -r ./build && npm run build"},"devDependencies":{"@pisa-research/utils":"^0.1.39","@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","np":"^6.2.1"},"dependencies":{"@any-sender/client":"^0.2.0-beta.0","@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","bn.js":"^5.1.1","ethers":"^4.0.43","npm":"^6.14.4","secure-random":"^1.1.2","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"gitHead":"ec02ff3b749f46a8878b56477371fc37581babf3","_id":"@anydotcrypto/metatransactions@0.0.8","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-9XrV9E8B2BX2QnkMpyVcI718InKILtrGebj1LsVZ8zOoEzbEKD2fyT5O0d5sN+ctylEq/hxEBGPHrP0JOLfiMQ==","shasum":"0c53a665193f0061c4052642136cf3b740efaa52","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.8.tgz","fileCount":73,"unpackedSize":500224,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeqgDyCRA9TVsSAnZWagAAzzsP/jm+drx7L9t7qrF3mocY\n3kcZ/zGAKyBgM4EMz+JhJoqRVEXnmqQggNviu2Kb3SuovMRy312uHXi1TgxD\njBGpYjHQLYA0uNSvedYwryyENLcY/r7pkrQMd+oEl6hy0WzAmUE8mOll5Md6\nThspUwvHk59dGCVgvhH1YdaFnH4GtmvSz2BKEgTiNUvHkUG7KikTXb8SHcxH\nahxAR/1+omH793dvhb9hWOYuzvlLpx+Mb3EhWSd39HunM+fQJurvPWm//kVG\n5uW6bjVkCcKKx0eYMahwIejKnOdvAWXsiUGqKIerg5vWV9d4ODeB7l6WMGPn\nBQA2IObnDvR/seT8gea2G4KA4yPGE3rGgEHxr/aGaJ9H2EqJQskc29ILrAEh\nnchr1KDEV8RAz7GMvebxl02ftU7QIHZZslMh0wKeKtFDIgkM67W1y0zKBsi0\nmVAFJIT6zzqRWmVKcZT9vih7Pw0IMsLZcTsd0DkvMI8Zsku7Sqd/ra4p2SaT\nTkCYXiIV/W99VxUvg04N0sPtbK1hlXJvfi9ISNDqIlMv76FmfgGM+kZeIR7x\nYar+ZrB12wN7LQxxytIvI8t/UZ4Vk505eZGiGD0FCt+V/LBOYkafPtJMVVGm\nSYfJGlWhaSSiS0IkSeZGEUCq4wecTXqpNpetCZTBzR2tRjYzsgrYgD7UeORZ\nO/JZ\r\n=r7lx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCooYdI1ByE7E1lQF6YJ9fYDhdvtZnQL6KB4PiUVzZxqwIgOxe2iiYAvLmZa578bqVusWNanTehy+pawk8mIzhfJpY="}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.8_1588199665195_0.6466020837743627"},"_hasShrinkwrap":false},"0.0.9":{"name":"@anydotcrypto/metatransactions","version":"0.0.9","description":"A minimal approach for meta-transaction support.","main":"dist/src/index.js","types":"dit/src/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts && tsc -p tsconfig.json && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run runtest -- --timeout='30000'","prepublish":"rm -r ./dist && rm -r ./build && npm run build"},"devDependencies":{"@pisa-research/utils":"^0.1.39","@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","np":"^6.2.1"},"dependencies":{"@any-sender/client":"^0.2.0-beta.0","@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","bn.js":"^5.1.1","ethers":"^4.0.43","npm":"^6.14.4","secure-random":"^1.1.2","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"gitHead":"3efa97278211567e5e1dd7cb2418299c99d2f83d","_id":"@anydotcrypto/metatransactions@0.0.9","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-+QlS/EQU57ibzE3JuVa+E4uqC9fB2b3yCQdZRnoDVOlzDtWvMpoqAPP0CpxX8nT2lE++282DEzjLx4jSP74o6w==","shasum":"066382c34337f54c854ae661150d3e3dc6431678","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.9.tgz","fileCount":73,"unpackedSize":500548,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeqqGgCRA9TVsSAnZWagAAQDMQAIfIZhZCVIxR/PwKMJrM\nMAM+Z44qppidVZXOkcEynoQ6mAWGkfIPjQSIQZMBM7aDoqDMdk623VIVg8S2\nvBdx/oNKJCck0ymjy30a9NCy1lROzK/nkZRX2vw2UPArpJT6H7TCft1ieolt\ntATq6LpOZ44QPoc2QHZO1yM4gOq+I15cpNZkiF/ZqbJHvfgt0/2Fec8O1qL3\nM0c5jHo4w1CFCGMUgHsrNErDQv9brgENQZglMYVXneH6bU4ShUxVQOpid/f2\nanmFit+rvbEUDNwgUN/zjsWuQyVxd0y+dKg8S/v0zUjqpa//0EPdnHs/SxjF\nAuK6wtL/pwVkESPJluY0YhmSUsmhGaEvcawDG+ICI8wTkKY4aSmWPJv8YbVR\neM+cEobqhIb6Qn4sRF5pOWXpkD2syA9FWgkfVqnBLUlqBo+SPLhvszGFcPlp\ntXDe4WylUPc3dVz1kXFufmJsruqgYka1NTn9cGZZa3ztskMLQ4ggwhzOfGb0\nvjAGWRAAsgpaEw/u14yIDeLOqNmS8wXGKEDVoPlohBkKm+/K9AFKmGjolLUy\now8ttRZG3IsWIP/UYReiBQ8xGshUtu2afVGNQzyc17a7+Z4STxISjPDVTZtd\nFnRiLHGnG1SLyQI7Spf0j2wD40PIZZaovR8s8l6USu/oECGsnEQxf6xOvmW+\np7aj\r\n=bhCr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBENLVD0wzWmDNW+LpeRNxelqbkjmaPbmK9nRp3I7s+aAiEA3qUAaGp+Pqxb9Epv1ZX+KSA6T3gygUTDTCIlBLwHJOs="}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.9_1588240799833_0.6857435671299106"},"_hasShrinkwrap":false},"0.0.10":{"name":"@anydotcrypto/metatransactions","version":"0.0.10","description":"A minimal approach for meta-transaction support.","main":"dist/src/index.js","types":"dit/src/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts && tsc -p tsconfig.json && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run runtest -- --timeout='30000'","prepublish":"rm -r ./dist && rm -r ./build && npm run build"},"devDependencies":{"@pisa-research/utils":"^0.1.39","@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","np":"^6.2.1"},"dependencies":{"@any-sender/client":"^0.2.0-beta.0","@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","bn.js":"^5.1.1","ethers":"^4.0.43","npm":"^6.14.4","secure-random":"^1.1.2","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"gitHead":"704048ab97f3e987738951ddf86d1932d869e5ed","_id":"@anydotcrypto/metatransactions@0.0.10","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-N49DeoqKMPgyy0Ui9XFpjy7VZGzLyRMYm1kL9otoyPXfs94IerxJMUHvm/YfVAVBbNZ/l3I3jCqD1H+Hr3m7cQ==","shasum":"53123f979d01c8d9f0a8633b8d0ba47a2215f0a8","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.10.tgz","fileCount":73,"unpackedSize":500518,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeqx7CCRA9TVsSAnZWagAAXwEP/AjcFwpqHSR2kXlO1dqz\naiQLlONNIYSJFFhSOs5C1ejZx/9GdmoL2iEhpzikVr2JCXaFPs1jnO3fN/q/\nKLMyrQECVWll+c5lq/l9aFOR4ivL/M1rsAp4eo64EKNRiGh8viMFfQG0huNI\ne5eCqoPjP7WJwq1JE7xFPzzOu7Ooz6NAdRFSyybojZUYAaLL6Sf+v3xRcVSG\ns8ERCxU/5FtTe1D89vyH3JWrDnbLfHc/lfRR+zhBXK+gDXb/pW0VnANg2FkK\nc3aCbktG3qsCnOE5Zr3gDTjFg7OOQIaxQaogRcpO1cflQ2yASJ9nrKTlph3J\noHk9x4LCf4UN68ujBTgmyzkhZJIAiu7LxYD6dJls4D6iPa9Z0vrjj2Qat3ws\nA8SXG5excEn1LyARWpSCf594pa9bWNmSbz24n2P2vPJE3Ym//vMYIX4FsCo0\nCTHjYXODjF+Zbdl7R1IPKrD8qX7HxnrCYPpgKf2ZdSj5bzL7NVhfcj0N5M7N\nVN/2Fn70yQuFTKu9YeM0dNiJNg6fr7p3pZNGvrArOL17CeQK0Q8uN/w+JRDm\n7qMdRZlsr9vnwyBrs7dKT6hmJ1aOaT3G7OQr5h4S/d/HqH6pejvHcj6mRj3D\ne52Kuklbbe9GITll+YNc4AmLVvdYBrrDTjfoQRM0PXxR9hBTQ0eibch5bMMd\n/rid\r\n=hybm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCgdN3ruOcAS29usKAwLhvaQXRvs2Z4c/BK04hSw/cwmgIhAJ/SzECV1IDwG4dpO5GHJlc9/huJm75bBWM3qC7Q5EhO"}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.10_1588272833568_0.7587695428282055"},"_hasShrinkwrap":false},"0.0.11-0":{"name":"@anydotcrypto/metatransactions","version":"0.0.11-0","description":"A minimal approach for meta-transaction support.","main":"dist/src/index.js","types":"dit/src/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts && tsc -p tsconfig.json && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run runtest -- --timeout='30000'","clean":"rm -r ./dist && rm -r ./build","prepublish":"npm run clean && npm run build"},"devDependencies":{"@pisa-research/utils":"^0.1.39","@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","np":"^6.2.1"},"dependencies":{"@any-sender/client":"^0.2.0-beta.0","@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","bn.js":"^5.1.1","ethers":"^4.0.43","npm":"^6.14.4","secure-random":"^1.1.2","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contracts:** All transactions for the user are sent via a proxy contract and it is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a global RelayHub.sol contract and the target contract must support the standard which requires it to replace msg.sender with \\_msgSender(). It is only compatible with contracts that have upgraded to use the standard.\n\nWe have put together this meta-transaction library to support both approaches. We hope it will benefit the community in the following ways:\n\n- **Ease of adoption:** All new smart contracts can support meta-transactions without handling replay protection (e.g. the permit() standard).\n- **Global RelayHub:** Our minimal RelayHub.sol can be a candidate for the hard-coded RelayHub in the \\_msgSender() standard.\n- **Single client library:** There are several libraries for constructing and signing transactions, but more often than not it is mixed up with the application logic. This repository is designed to become a single standard any project can adopt.\n\nFinally, the ultimate goal is to make it easier for developers to tap into third party relayer APIs that focus on getting transactions in the blockchain.\n\n## Getting started\n\nWe assume you have already set up your environment and you simply need to plug-in our library.\n\n1. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. You need to import the package into your file:\n\n```\nimport { ChainID, ReplayProtectionType, ForwarderFactory } from \"@anydotcrypto/metatransactions/dist\";\n```\n\n3. You need to decide which the network, replay protection, and the msg.sender solution.\n\nWe have support for two networks:\n\n```\nChainID.MAINNET\nChainID.ROPSTEN\n```\n\nOur library contains three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Replace-by-nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nThe enumeration is simpe:\n\n```\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\nReplayProtectionType.MULTINONCE // N queues\nReplayProtectionType.NONCE // Single queue\n```\n\nFor the msg.sender solution, we cover [ProxyAccountFactory vs RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub) later in the README. If you are unsure which one to use, then we recommend `ContractType.PROXYACCOUNTDEPLOYER` as it works for all existing contracts. Essentially, each user has a minimal proxy account contract and their meta-transaction is sent via the proxy. The target's msg.sender is the proxy contract's address.\n\n4. Time to instantiate the forwarder library!\n\nIf you want to use Proxy Accounts:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst concurrency = 10;\nconst forwarder = ForwarderFactory.getProxyForwarder(ChainID.MAINNET, ReplayProtectionType.MULTINONCE, signer);\n```\n\nThe above option configures the proxy accounts to use multi-nonce replay protection (with 30 nonce queues). If you want all transactions to be processed in the transaction by order, then just set `ReplayProtectionType.NONCE`.\n\nIf you want to use the RelayHub:\n\n```\nconst signer = wallet.Mnemonic(\"\");\nconst forwarder = ForwarderFactory.getRelayHubForwarder(ChainID.MAINNET, ReplayProtectType.BITFLIP, signer);\n```\n\nThe above configures the relay hub to use the bitflip replay protection. Bitflip supports an _unlimited number of concurrent transactions_ which is useful for batch withdrawals. It does not support ordered transactions, so use replace-by-nonce if you require ordering.\n\n5. You are now ready to authorise a meta-transaction using the ForwarderFactory.\n\n```\nconst user = Wallet.fromMnemonic(\"\");\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.broadcastMessage.encode([\"to the moon\"]);\nconst value = new BigNumber(\"0\");\n\nconst forwarder = ForwarderFactory.getProxyForwarder(ChainID.MAINNET, ReplayProtectionType.MULTINONCE, signer);\nconst data = {target: echo.address, value: value, callData: callData}; // Explicit tutorial\nconst params = await forwarder.signMetaTransaction({target: echo.address, value, data}) ;\n```\n\nThe forwarder just requires:\n\n- Target contract's address,\n- Value to be sent (proxy fowarder only)\n- Desired calldata (function name and its arguments).\n\nIt takes care of the replay protection (multinonce/bitflip) and authorising the meta-transaction under the hood. The returned `params` can be used to send the meta-transaction to Ethereum:\n\n```\nconst relayer = Wallet.fromMnemonic(\"\");\n\n// All meta-transactions for ProxyAccountFactory are sent from the user's ProxyAccount contract.\n// We assume it is already deployed on the network. Look at the ProxyAccountFactory section to\n// find out more (super-easy to deploy).\nconst proxyAccount = new ProxyAccountFactory(relayer).attach(params.to);\nconst tx = await proxyAccount\n        .connect(relayer)\n        .forward(\n          params.target,\n          params.value,\n          params.data,\n          params.replayProtection,\n          params.replayProtectionAuthority,\n          params.signature\n        );\n\n```\n\n### All done! Good work!\n\nHere is a full example:\n\n```\n// What contract and function do we want to execute? And who is the signer?\nconst user = Wallet.fromMnemonic(\"\");\nconst targetContract = new EchoFactory(user).attach(\"\");\nconst value = new BigNumber(\"0\");\nconst callData = targetContract.interface.functions.test.encode([]);\n\n// Prepare and authorise the meta-transaction\nconst forwarder = ForwarderFactory.getProxyForwarder(ChainID.MAINNET, ReplayProtectionType.MULTINONCE, signer);\nconst params = await forwarder.signMetaTransaction({ target: targetContract.address, value, callData }) ;\n\n// Relayer publishes transaction\nconst relayerWallet Wallet.fromMnemonic(\"\");\nconst encodedMetaTx = forwarder.encodeMetaTransaction(params);\nconst tx = await relayerWallet.sendTransaction( {to: params.to, data: encodedMetaTx}) );\nconst receipt = await tx.wait(1)\n```\n\nAs we can see in the above, it is easy for the user to craft and sign a meta-transaction for the target contract. The `params` (or its encoding) can be wrapped in an Ethereum transaction and sent to the blockchain.\n\n## ProxyAccount vs RelayHub\n\nAs we mentioned earlier, there are two solutions to the msg.sender problem.\n\n- **ProxyAccountDeployer**: Deploys a proxy account contract for the user with a deterministic address. All meta-transactions are sent via the user's proxy account.\n- **RelayHub**: There is no proxy account contracts. The RelayHub appends the signer's address onto the calldata that is sent to the target contract. It requires the target contract to support the \\_msgSender() standard.\n\nWhile the ProxyAccountDeployer works for all existing smart contracts, the RelayHub requires the target contract to support the \\_msgSender() standard. If supported, the RelayHub allows the signer's address to be the msg.sender in the target contract. Going forward, we hope that the RelayHub serves as a model and it can later become a precompile/a new opcode in Ethereum.\n\nNote, the one big difference between the ProxyAccountDeployer and the RelayHub is the forward() function. ProxyAccountDeployer lets the user set `value` of ETH that can be sent (e.g. the proxy account can have an ETH balance) in the meta-transaction. However, the RelayHub does not have a `value` argument and does not support sending ETH. See [this issue](https://github.com/anydotcrypto/metatransactions/issues/9) to find out why.\n\n### Proxy Hub\n\nIt is a central registry contract that is responsible for deploying proxy contracts (`ProxyAccount.sol`). Every proxy contract is destinated for a single user and it has a deterministic address via CREATE2. We use the [CloneFactory](https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol) to minimise storage overhead on the network.\n\nThere is only one function to care about:\n\n```\nconst user = Wallet.fromMnemonic(\"\");\nawait proxyDeployer.createProxyContract(user.address);\n```\n\nIt deploys a new `ProxyAccount` for the user and then stores a record of it in the ProxyAccountDeployer. Our ProxyAccount is a minimal contract that checks the user's signed the meta-transaction and the replay protection is valid. It only has two functions:\n\n- **DeployContract contracts**: Deploys a new smart contract with a deterministic address.\n\n```\nawait proxyAccount.deployContract(\n          initData: string, // Bytecode of the contract\n          replayProtection: string, // Encoding of replay protection (nonce1, nonce2)\n          replayProtectionAuthority: string, // Address (default is 0x00....)\n          signature: string // Signer's signature (address stored in proxy)\n        );\n\n```\n\n- **Forward**: Calls out to the target contract with the user's desired calldata.\n\n```\nawait proxyAccount.forward(\n        target: string, // Contract address\n        value: BigNumber, // ETH to send\n        data: string, // Calldata\n        replayProtection: string, // Encoding of replay protection (nonce1, nonce2)\n        replayProtectionAuthority: string, // Address (default is 0x00....)\n        signature: string // Signer's signature (address stored in proxy)\n);\n```\n\nLet's look at a full code example.\n\n```\n// Who is our signer?\nconst user = Wallet.fromMnemonic(\"\");\nconst relayer = Wallet.fromMnemonic(\"\");\n\n\n// Deploying a smart contract\nconst echoFactory = new EchoFactory(user);\nconst initCode = echoFactory.getDeployTransaction().data! as string; // Constructor arguments accepted\n\n// Set up meta-transaction handler and sign meta-deployment\nconst forwarder = ForwarderFactory.multinonce(ChainID.MAINNET, ContractType.PROXYACCOUNTDEPLOYER, 100);\nconst params = await forwarder.signMetaDeployment(user, initCode);\n\n// Send to the network via the ProxyAccount sends transaction to network (or sent up to Relayer API)\n// Fetch the proxy account\nconst encodedMetaDeployment = forwarder.encodeMetaDeployment(params);\nconst tx = await relayer.sendTransaction({to: params.to, data: encodedMetaDeployment});\n\n// Compute deterministic address for the deployed contract (helper function coming soon)\nconst hByteCode = arrayify(keccak256(initCode));\nconst encodeToSalt = defaultAbiCoder.encode([\"address\", \"bytes\"],[signer.address, params.replayProtection]);\nconst salt = arrayify(keccak256(encodeToSalt));\nconst echoAddress = await proxyAccount.connect(relayer).computeAddress(salt, hByteCode);\n\n// Fetch the echo contract\nconst echoContract = echoFactory.attach(echoAddress);\n\n// Sending the meta-transaction\nconst callData = echoContract.interface.functions.broadcastMessage.encode([]);\nconst value = new BigNumber(\"0\");\nconst params = await forwarder.signMetaTransaction(\n        {to: echoContract.address,\n        value,\n        callData}\n      );\n\n// Send to Ethereum (or send up to the RelayerAPI)\nconst tx = proxyAccount.connect(relayer).forward(\n        params.target,\n        params.value,\n        params.data,\n        params.replayProtection,\n        params.replayProtectionAuthority,\n        params.signature\n);\n```\n\n### Relay Hub\n\nIt is a central registry contract that keeps track of the signer's address and the state of their replay protection. It can only be used with smart contracts that support the \\_msgSender() standard and inherit [MsgSender](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/account/MsgSender.sol). The global singleton [RelayHub](https://etherscan.io/address/0x70107abb312db18bd9addec39ce711374b09ebc1) must be hard-coded into the target contract. We hope it will become a standard that has community support & it can be included in all new contracts.\n\nThe benefit of the RelayHub is that the signer's address is set as the msg.sender and there are no proxy contracts. Thus, it is more natural for the user who wants to look up their address in the contract. We hope our RelayHub will eventually become a new precompile or opcode in Ethereum - which may ultimately solve the msg.sender problem for relay transactions.\n\nIt only has two functions:\n\n- **DeployContract contracts**: Deploys a new smart contract with a deterministic address.\n\n```\nawait relayHub.deployContract(\n          initData: string, // Bytecode of the contract\n          replayProtection: string, // Encoding of replay protection (nonce1, nonce2)\n          replayProtectionAuthority: string, // Address (default is 0x00....)\n          signature: string // Signer's signature (address stored in proxy)\n        );\n```\n\n- **Forward**: Calls out to the target contract with the user's desired calldata. The signer's address is appended to the calldata sent to the target contract.\n\n```\nawait relayHub.forward(\n        target: string, // Contract address\n        data: string, // Calldata\n        replayProtection: string, // Encoding of replay protection (nonce1, nonce2)\n        replayProtectionAuthority: string, // Address (default is 0x00....)\n        signature: string // Signer's signature (address stored in proxy)\n);\n```\n\nHere is a code example for both:\n\n```\n// Who is our signer?\nconst user = Wallet.fromMnemonic(\"\");\nconst relayer = Wallet.fromMnemonic(\"\");\n\n// Deploying a smart contract\nconst echoFactory = new EchoFactory(user);\nconst initCode = echoFactory.getDeployTransaction().data! as string; // Constructor arguments accepted\n\n// Set up meta-transaction handler and sign meta-deployment\nconst forwarder = ForwarderFactory.multinonce(ChainID.MAINNET, ContractType.RELAYHUB, 100);\nconst params = await forwarder.signMetaDeployment(user, initCode);\n\n// Relayer sends transaction to network\nconst relayHubAddress = ForwarderFactory.getHubAddress(ChainID.MAINNET, ContractType.RELAYHUB);\nconst relayHub = new RelayHubFacotry(relayer).attach(relayHubAddress);\nconst tx = await relayHub.connect(relayer).deployContract(\n          params.data,\n          params.replayProtection,\n          params.replayProtectionAuthority,\n          params.signature\n        );\n\n// Compute deterministic address for the deployed contract (helper function coming soon)\nconst hByteCode = arrayify(keccak256(initCode));\nconst encodeToSalt = defaultAbiCoder.encode([\"address\", \"bytes\"],[signer.address, params.replayProtection]);\nconst salt = arrayify(keccak256(encodeToSalt));\nconst echoAddress = await relayHub.connect(relayer).computeAddress(salt, hByteCode);\n\n// Fetch the echo contract\nconst echoContract = echoFactory.attach(echoAddress);\n\n// Sending the meta-transaction\nconst callData = echoContract.interface.functions.broadcastMessage.encode([]);\nconst value = new BigNumber(\"0\");\nconst params = await forwarder.signMetaTransaction(\n        user,\n        echoContract.address,\n        value,\n        callData\n      );\n\n// Send to Ethereum (or send up to the RelayerAPI)\nconst tx = relayHub.connect(relayer).forward(\n        params.target,\n        params.data,\n        params.replayProtection,\n        params.replayProtectionAuthority,\n        params.signature\n);\n```\n\n## How to build and test the library locally\n\nWe need to install the NPM packages:\n\n```\nnpm i\n```\n\nThen we can simply build and test:\n\n```\nnpm run build && npm run test\n```\n\n## Where is the ProxyAccountFactory and RelayHub?\n\nWe have deployed the latest version of the ProxyAccountFactory and RelayHub. The links can be found below.\n\nMainnet:\n\n- [ProxyAccountFactory](https://etherscan.io/address/0xE139c086d9EEC16cBaF5a125FFf748939Fb734f1)\n- [RelayHub](https://etherscan.io/address/0x36892A63E99d66d01766e227F3cCc6235dE09eD9)\n\nRopsten:\n\n- [ProxyAccountFactory](https://ropsten.etherscan.io/address/0x5A60af44A45d11Cefd0182cb0514cce3149a0445)\n- [RelayHub](https://ropsten.etherscan.io/address/0xf4cb3Ff902f8fE23f3638Eb6F33B467c4180e605)\n\nThanks for checking out this code repository. It was first motivated by EIP-2585 and the RelayHub standard by the GSN.\n","readmeFilename":"README.md","gitHead":"777f4a6f363c30bdbab7e5cf294234e45f197a6b","_id":"@anydotcrypto/metatransactions@0.0.11-0","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-534f9F5lwfF2ZAJ6phYwvdA0QxoI8HDFRq4oa7lsHbCZntxjZy4uOGSaqrEz02P2Ns1/s0MPanZuXUgvzebijA==","shasum":"edeb5916dd3161982288d391c9dd95f40ebb95e1","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.11-0.tgz","fileCount":85,"unpackedSize":514281,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJer+yACRA9TVsSAnZWagAAOboP/16et7Dm8s6dAu0ksPKt\nb0ScUoCLcTzNbD2RagaiYbEDlguBUfVKKzrg5366SB0cZcothzuj72OgLpr7\nFSlJL/xGFbIEMQknuILfWCDZjDefNsNF3/wl8gXx76PMhB5emfVITZAwKjQ+\n/jhZqtF31xAzuG/SWoh4Btm62svvWLKNrqhPCGI/IR7LXzrT2hPf7S8UyFfo\nXvbqFL/rC2o+PkThbIslqLc/Qs7jvp73ErqRevkZULXyH16UPIobROrWkX0p\nQgd+1cdq//cRlOGZOSssPCqB1qCvTIaq0rynhYrO4fPDJzGZlTIwpCTi81pb\nEdZiKmnjLURp36j4wfGc8Jl5OiJy1k1PdEriz1zcMwbanEnZpCROdpWmKrVi\nEIXl13YqylNOVMB/tU+Vs/kXISSKHjvczSmhwBUjtgcCsjntgjuCAQ95yq4E\nG1l5wPql9qLYkRjxZEuCFFO5EUNXBumnkMjog1l9GYvVLBCai2OH6VoJg62t\nNbltbXSANnAYMue/WZWi5tFa9iMZbPrSrugbj3cPBEI38Ek5O421ECk2ubw6\n9fPY3c1rhO6qp384ZxFYrjoeYHm2h4E4l2rWdBJl/joqxGb1nUeTE7uLQI0q\nSDF4nbR4XOUG74lF0EVabqhEmLFmCwM/rChdAGwR1W3qZX6gLK8lFiM+JxQR\nSH1k\r\n=3e7Z\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDUskYiGJVgL/u5TmZS3AFtwI2qxn4nUqf19gBoW644bAiEAxyG21YMEgkrihDhyW0buyxJeVHOQLAoJX51VIacpmSU="}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.11-0_1588587648223_0.7390882653407518"},"_hasShrinkwrap":false},"0.0.11-1":{"name":"@anydotcrypto/metatransactions","version":"0.0.11-1","description":"A minimal approach for meta-transaction support.","main":"dist/src/index.js","types":"dit/src/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts && tsc -p tsconfig.json && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run runtest -- --timeout='30000'","clean":"rm -r ./dist && rm -r ./build","prepublishOnly":"npm run clean && npm run build"},"devDependencies":{"@pisa-research/utils":"^0.1.39","@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","np":"^6.2.1"},"dependencies":{"@any-sender/client":"^0.2.0-beta.0","@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","bn.js":"^5.1.1","ethers":"^4.0.43","npm":"^6.14.4","secure-random":"^1.1.2","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contracts:** All transactions for the user are sent via a proxy contract and it is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a global RelayHub.sol contract and the target contract must support the standard which requires it to replace msg.sender with \\_msgSender(). It is only compatible with contracts that have upgraded to use the standard.\n\nWe have put together this meta-transaction library to support both approaches. We hope it will benefit the community in the following ways:\n\n- **Ease of adoption:** All new smart contracts can support meta-transactions without handling replay protection (e.g. the permit() standard).\n- **Global RelayHub:** Our minimal RelayHub.sol can be a candidate for the hard-coded RelayHub in the \\_msgSender() standard.\n- **Single client library:** There are several libraries for constructing and signing transactions, but more often than not it is mixed up with the application logic. This repository is designed to become a single standard any project can adopt.\n\nFinally, the ultimate goal is to make it easier for developers to tap into third party relayer APIs that focus on getting transactions in the blockchain.\n\n## Getting started\n\nWe assume you have already set up your environment and you simply need to plug-in our library.\n\n1. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. You need to import the package into your file:\n\n```\nimport { ChainID, ReplayProtectionType, ForwarderFactory } from \"@anydotcrypto/metatransactions/dist\";\n```\n\n3. You need to decide which the network, replay protection, and the msg.sender solution.\n\nWe have support for two networks:\n\n```\nChainID.MAINNET\nChainID.ROPSTEN\n```\n\nOur library contains three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Replace-by-nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nThe enumeration is simpe:\n\n```\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\nReplayProtectionType.MULTINONCE // N queues\nReplayProtectionType.NONCE // Single queue\n```\n\nFor the msg.sender solution, we cover [ProxyAccountFactory vs RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub) later in the README. If you are unsure which one to use, then we recommend `ContractType.PROXYACCOUNTDEPLOYER` as it works for all existing contracts. Essentially, each user has a minimal proxy account contract and their meta-transaction is sent via the proxy. The target's msg.sender is the proxy contract's address.\n\n4. Time to instantiate the forwarder library!\n\nIf you want to use Proxy Accounts:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst concurrency = 10;\nconst forwarder = ForwarderFactory.getProxyForwarder(ChainID.MAINNET, ReplayProtectionType.MULTINONCE, signer);\n```\n\nThe above option configures the proxy accounts to use multi-nonce replay protection (with 30 nonce queues). If you want all transactions to be processed in the transaction by order, then just set `ReplayProtectionType.NONCE`.\n\nIf you want to use the RelayHub:\n\n```\nconst signer = wallet.Mnemonic(\"\");\nconst forwarder = ForwarderFactory.getRelayHubForwarder(ChainID.MAINNET, ReplayProtectType.BITFLIP, signer);\n```\n\nThe above configures the relay hub to use the bitflip replay protection. Bitflip supports an _unlimited number of concurrent transactions_ which is useful for batch withdrawals. It does not support ordered transactions, so use replace-by-nonce if you require ordering.\n\n5. You are now ready to authorise a meta-transaction using the ForwarderFactory.\n\n```\nconst user = Wallet.fromMnemonic(\"\");\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.broadcastMessage.encode([\"to the moon\"]);\nconst value = new BigNumber(\"0\");\n\nconst forwarder = ForwarderFactory.getProxyForwarder(ChainID.MAINNET, ReplayProtectionType.MULTINONCE, signer);\nconst data = {target: echo.address, value: value, callData: callData}; // Explicit tutorial\nconst params = await forwarder.signMetaTransaction({target: echo.address, value, data}) ;\n```\n\nThe forwarder just requires:\n\n- Target contract's address,\n- Value to be sent (proxy fowarder only)\n- Desired calldata (function name and its arguments).\n\nIt takes care of the replay protection (multinonce/bitflip) and authorising the meta-transaction under the hood. The returned `params` can be used to send the meta-transaction to Ethereum:\n\n```\nconst relayer = Wallet.fromMnemonic(\"\");\n\n// All meta-transactions for ProxyAccountFactory are sent from the user's ProxyAccount contract.\n// We assume it is already deployed on the network. Look at the ProxyAccountFactory section to\n// find out more (super-easy to deploy).\nconst proxyAccount = new ProxyAccountFactory(relayer).attach(params.to);\nconst tx = await proxyAccount\n        .connect(relayer)\n        .forward(\n          params.target,\n          params.value,\n          params.data,\n          params.replayProtection,\n          params.replayProtectionAuthority,\n          params.signature\n        );\n\n```\n\n### All done! Good work!\n\nHere is a full example:\n\n```\n// What contract and function do we want to execute? And who is the signer?\nconst user = Wallet.fromMnemonic(\"\");\nconst targetContract = new EchoFactory(user).attach(\"\");\nconst value = new BigNumber(\"0\");\nconst callData = targetContract.interface.functions.test.encode([]);\n\n// Prepare and authorise the meta-transaction\nconst forwarder = ForwarderFactory.getProxyForwarder(ChainID.MAINNET, ReplayProtectionType.MULTINONCE, signer);\nconst params = await forwarder.signMetaTransaction({ target: targetContract.address, value, callData }) ;\n\n// Relayer publishes transaction\nconst relayerWallet Wallet.fromMnemonic(\"\");\nconst encodedMetaTx = forwarder.encodeMetaTransaction(params);\nconst tx = await relayerWallet.sendTransaction( {to: params.to, data: encodedMetaTx}) );\nconst receipt = await tx.wait(1)\n```\n\nAs we can see in the above, it is easy for the user to craft and sign a meta-transaction for the target contract. The `params` (or its encoding) can be wrapped in an Ethereum transaction and sent to the blockchain.\n\n## ProxyAccount vs RelayHub\n\nAs we mentioned earlier, there are two solutions to the msg.sender problem.\n\n- **ProxyAccountDeployer**: Deploys a proxy account contract for the user with a deterministic address. All meta-transactions are sent via the user's proxy account.\n- **RelayHub**: There is no proxy account contracts. The RelayHub appends the signer's address onto the calldata that is sent to the target contract. It requires the target contract to support the \\_msgSender() standard.\n\nWhile the ProxyAccountDeployer works for all existing smart contracts, the RelayHub requires the target contract to support the \\_msgSender() standard. If supported, the RelayHub allows the signer's address to be the msg.sender in the target contract. Going forward, we hope that the RelayHub serves as a model and it can later become a precompile/a new opcode in Ethereum.\n\nNote, the one big difference between the ProxyAccountDeployer and the RelayHub is the forward() function. ProxyAccountDeployer lets the user set `value` of ETH that can be sent (e.g. the proxy account can have an ETH balance) in the meta-transaction. However, the RelayHub does not have a `value` argument and does not support sending ETH. See [this issue](https://github.com/anydotcrypto/metatransactions/issues/9) to find out why.\n\n### Proxy Hub\n\nIt is a central registry contract that is responsible for deploying proxy contracts (`ProxyAccount.sol`). Every proxy contract is destinated for a single user and it has a deterministic address via CREATE2. We use the [CloneFactory](https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol) to minimise storage overhead on the network.\n\nThere is only one function to care about:\n\n```\nconst user = Wallet.fromMnemonic(\"\");\nawait proxyDeployer.createProxyContract(user.address);\n```\n\nIt deploys a new `ProxyAccount` for the user and then stores a record of it in the ProxyAccountDeployer. Our ProxyAccount is a minimal contract that checks the user's signed the meta-transaction and the replay protection is valid. It only has two functions:\n\n- **DeployContract contracts**: Deploys a new smart contract with a deterministic address.\n\n```\nawait proxyAccount.deployContract(\n          initData: string, // Bytecode of the contract\n          replayProtection: string, // Encoding of replay protection (nonce1, nonce2)\n          replayProtectionAuthority: string, // Address (default is 0x00....)\n          signature: string // Signer's signature (address stored in proxy)\n        );\n\n```\n\n- **Forward**: Calls out to the target contract with the user's desired calldata.\n\n```\nawait proxyAccount.forward(\n        target: string, // Contract address\n        value: BigNumber, // ETH to send\n        data: string, // Calldata\n        replayProtection: string, // Encoding of replay protection (nonce1, nonce2)\n        replayProtectionAuthority: string, // Address (default is 0x00....)\n        signature: string // Signer's signature (address stored in proxy)\n);\n```\n\nLet's look at a full code example.\n\n```\n// Who is our signer?\nconst user = Wallet.fromMnemonic(\"\");\nconst relayer = Wallet.fromMnemonic(\"\");\n\n\n// Deploying a smart contract\nconst echoFactory = new EchoFactory(user);\nconst initCode = echoFactory.getDeployTransaction().data! as string; // Constructor arguments accepted\n\n// Set up meta-transaction handler and sign meta-deployment\nconst forwarder = ForwarderFactory.multinonce(ChainID.MAINNET, ContractType.PROXYACCOUNTDEPLOYER, 100);\nconst params = await forwarder.signMetaDeployment(user, initCode);\n\n// Send to the network via the ProxyAccount sends transaction to network (or sent up to Relayer API)\n// Fetch the proxy account\nconst encodedMetaDeployment = forwarder.encodeMetaDeployment(params);\nconst tx = await relayer.sendTransaction({to: params.to, data: encodedMetaDeployment});\n\n// Compute deterministic address for the deployed contract (helper function coming soon)\nconst hByteCode = arrayify(keccak256(initCode));\nconst encodeToSalt = defaultAbiCoder.encode([\"address\", \"bytes\"],[signer.address, params.replayProtection]);\nconst salt = arrayify(keccak256(encodeToSalt));\nconst echoAddress = await proxyAccount.connect(relayer).computeAddress(salt, hByteCode);\n\n// Fetch the echo contract\nconst echoContract = echoFactory.attach(echoAddress);\n\n// Sending the meta-transaction\nconst callData = echoContract.interface.functions.broadcastMessage.encode([]);\nconst value = new BigNumber(\"0\");\nconst params = await forwarder.signMetaTransaction(\n        {to: echoContract.address,\n        value,\n        callData}\n      );\n\n// Send to Ethereum (or send up to the RelayerAPI)\nconst tx = proxyAccount.connect(relayer).forward(\n        params.target,\n        params.value,\n        params.data,\n        params.replayProtection,\n        params.replayProtectionAuthority,\n        params.signature\n);\n```\n\n### Relay Hub\n\nIt is a central registry contract that keeps track of the signer's address and the state of their replay protection. It can only be used with smart contracts that support the \\_msgSender() standard and inherit [MsgSender](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/account/MsgSender.sol). The global singleton [RelayHub](https://etherscan.io/address/0x70107abb312db18bd9addec39ce711374b09ebc1) must be hard-coded into the target contract. We hope it will become a standard that has community support & it can be included in all new contracts.\n\nThe benefit of the RelayHub is that the signer's address is set as the msg.sender and there are no proxy contracts. Thus, it is more natural for the user who wants to look up their address in the contract. We hope our RelayHub will eventually become a new precompile or opcode in Ethereum - which may ultimately solve the msg.sender problem for relay transactions.\n\nIt only has two functions:\n\n- **DeployContract contracts**: Deploys a new smart contract with a deterministic address.\n\n```\nawait relayHub.deployContract(\n          initData: string, // Bytecode of the contract\n          replayProtection: string, // Encoding of replay protection (nonce1, nonce2)\n          replayProtectionAuthority: string, // Address (default is 0x00....)\n          signature: string // Signer's signature (address stored in proxy)\n        );\n```\n\n- **Forward**: Calls out to the target contract with the user's desired calldata. The signer's address is appended to the calldata sent to the target contract.\n\n```\nawait relayHub.forward(\n        target: string, // Contract address\n        data: string, // Calldata\n        replayProtection: string, // Encoding of replay protection (nonce1, nonce2)\n        replayProtectionAuthority: string, // Address (default is 0x00....)\n        signature: string // Signer's signature (address stored in proxy)\n);\n```\n\nHere is a code example for both:\n\n```\n// Who is our signer?\nconst user = Wallet.fromMnemonic(\"\");\nconst relayer = Wallet.fromMnemonic(\"\");\n\n// Deploying a smart contract\nconst echoFactory = new EchoFactory(user);\nconst initCode = echoFactory.getDeployTransaction().data! as string; // Constructor arguments accepted\n\n// Set up meta-transaction handler and sign meta-deployment\nconst forwarder = ForwarderFactory.multinonce(ChainID.MAINNET, ContractType.RELAYHUB, 100);\nconst params = await forwarder.signMetaDeployment(user, initCode);\n\n// Relayer sends transaction to network\nconst relayHubAddress = ForwarderFactory.getHubAddress(ChainID.MAINNET, ContractType.RELAYHUB);\nconst relayHub = new RelayHubFacotry(relayer).attach(relayHubAddress);\nconst tx = await relayHub.connect(relayer).deployContract(\n          params.data,\n          params.replayProtection,\n          params.replayProtectionAuthority,\n          params.signature\n        );\n\n// Compute deterministic address for the deployed contract (helper function coming soon)\nconst hByteCode = arrayify(keccak256(initCode));\nconst encodeToSalt = defaultAbiCoder.encode([\"address\", \"bytes\"],[signer.address, params.replayProtection]);\nconst salt = arrayify(keccak256(encodeToSalt));\nconst echoAddress = await relayHub.connect(relayer).computeAddress(salt, hByteCode);\n\n// Fetch the echo contract\nconst echoContract = echoFactory.attach(echoAddress);\n\n// Sending the meta-transaction\nconst callData = echoContract.interface.functions.broadcastMessage.encode([]);\nconst value = new BigNumber(\"0\");\nconst params = await forwarder.signMetaTransaction(\n        user,\n        echoContract.address,\n        value,\n        callData\n      );\n\n// Send to Ethereum (or send up to the RelayerAPI)\nconst tx = relayHub.connect(relayer).forward(\n        params.target,\n        params.data,\n        params.replayProtection,\n        params.replayProtectionAuthority,\n        params.signature\n);\n```\n\n## How to build and test the library locally\n\nWe need to install the NPM packages:\n\n```\nnpm i\n```\n\nThen we can simply build and test:\n\n```\nnpm run build && npm run test\n```\n\n## Where is the ProxyAccountFactory and RelayHub?\n\nWe have deployed the latest version of the ProxyAccountFactory and RelayHub. The links can be found below.\n\nMainnet:\n\n- [ProxyAccountFactory](https://etherscan.io/address/0xE139c086d9EEC16cBaF5a125FFf748939Fb734f1)\n- [RelayHub](https://etherscan.io/address/0x36892A63E99d66d01766e227F3cCc6235dE09eD9)\n\nRopsten:\n\n- [ProxyAccountFactory](https://ropsten.etherscan.io/address/0x5A60af44A45d11Cefd0182cb0514cce3149a0445)\n- [RelayHub](https://ropsten.etherscan.io/address/0xf4cb3Ff902f8fE23f3638Eb6F33B467c4180e605)\n\nThanks for checking out this code repository. It was first motivated by EIP-2585 and the RelayHub standard by the GSN.\n","readmeFilename":"README.md","gitHead":"f1073207f63008031e3c4e03a88affc89191b6b9","_id":"@anydotcrypto/metatransactions@0.0.11-1","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-0bzVWciPh+uRqyw87CU6O3z/KbmNtem7d5anqkbw+tdjW3ORWme3K+sJz4Z0Wricb5+5LPUxKLCTp1DPKKGTWQ==","shasum":"b9266ea9b9d26c39de0ec8d8420d02b42787e9fa","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.11-1.tgz","fileCount":85,"unpackedSize":514856,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJer/59CRA9TVsSAnZWagAAUHkP/1CYuFPN7OrNqrVSuDqE\n3ZSUGMPnVFvMfHzwIKxdCUMeJ9/kLHGjBWIbr1LGN2F+JU37yPO5FALgvKtz\nug/IcW3ONZV3PFcTqD+/z5wJVADoMiLkxJT3RbuzsvcRqeSRSZqn13wnWM6o\nMBTmxoJ78hczHHemCab6GJevmH9LHKzukwGqt2huN6iotjiBl1y26YE4Zx2/\nebKiLcOOjuMQ+SwIUyC5sFp2ax6O5wPjHo//WutK7EcojRnT370VcwUSrbeY\nVzUkxkTnqHBBSRkaJEJi1dSJwj67ONrPsB1Tcr2c/Jx90mj8Bq2b+EZN/eF2\n8WXDqklzAPe+vceTCRpxY5zIv7lkaTpsej1qIbEMVPzYN0clKwv6lliBqenk\ngS2r6I51uKuSXgjQZ7rYtsEqbK88vkdgf4yGSZNxju8yNFuWvRgTKeoWW4b/\ntAE6JD/FyLZqmMBGqrM1SsPWouGdYCBk9vHyFmO0AJ/PApteZMFq8+nZ8TK7\nlDJC+fFUnRcSMNcCfxJ5Lh2tsDajuVd7jrr22kJWejODCGNEw4L5AxGCUfZ2\n7F9zspiKTLIgu/Vf9rdal3JhBROJQx1tdWAO8pnYWQOUK1abJsl9bdhTJVWT\naNVB2kZM7T7eihBcyKmmTeBgUO+d3KAqMxlu7gphlB095oxCrVTTkzbSHmWJ\nj/w/\r\n=bP2H\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCZMCHpxaij9awkmrLSoj7XtyU1zzE+qDoFWx/VDYLJYQIgaEeQ8VdxxPbJRqe+8i5ARWGYiDJb63aYxLDC2P9eKd0="}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.11-1_1588592253258_0.18333956828626774"},"_hasShrinkwrap":false},"0.0.11-2":{"name":"@anydotcrypto/metatransactions","version":"0.0.11-2","description":"A minimal approach for meta-transaction support.","main":"dist/src/index.js","types":"dit/src/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts && tsc -p tsconfig.json && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -r ./dist && rm -r ./build","prepublishOnly":"npm run clean && npm run build"},"devDependencies":{"@pisa-research/utils":"^0.1.39","@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","np":"^6.2.1"},"dependencies":{"@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","bn.js":"^5.1.1","ethers":"^4.0.43","npm":"^6.14.4","secure-random":"^1.1.2","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contracts:** All transactions for the user are sent via a proxy contract and it is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a global RelayHub.sol contract and the target contract must support the standard which requires it to replace msg.sender with \\_msgSender(). It is only compatible with contracts that have upgraded to use the standard.\n\nWe have put together this meta-transaction library to support both approaches. We hope it will benefit the community in the following ways:\n\n- **Ease of adoption:** All new smart contracts can support meta-transactions without handling replay protection (e.g. the permit() standard).\n- **Global RelayHub:** Our minimal RelayHub.sol can be a candidate for the hard-coded RelayHub in the \\_msgSender() standard.\n- **Single client library:** There are several libraries for constructing and signing transactions, but more often than not it is mixed up with the application logic. This repository is designed to become a single standard any project can adopt.\n\nFinally, the ultimate goal is to make it easier for developers to tap into third party relayer APIs that focus on getting transactions in the blockchain.\n\n## Getting started\n\nWe assume you have already set up your environment and you simply need to plug-in our library.\n\n1. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. You need to import the package into your file:\n\n```\nimport { ChainID, ReplayProtectionType, ForwarderFactory } from \"@anydotcrypto/metatransactions/dist\";\n```\n\n3. You need to decide which the network, replay protection, and the msg.sender solution.\n\nWe have support for two networks:\n\n```\nChainID.MAINNET\nChainID.ROPSTEN\n```\n\nOur library contains three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Replace-by-nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nThe enumeration is simpe:\n\n```\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\nReplayProtectionType.MULTINONCE // N queues\nReplayProtectionType.NONCE // Single queue\n```\n\nFor the msg.sender solution, we cover [ProxyAccountFactory vs RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub) later in the README. If you are unsure which one to use, then we recommend `ContractType.PROXYACCOUNTDEPLOYER` as it works for all existing contracts. Essentially, each user has a minimal proxy account contract and their meta-transaction is sent via the proxy. The target's msg.sender is the proxy contract's address.\n\n4. Time to instantiate the forwarder library!\n\nIf you want to use Proxy Accounts:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst concurrency = 10;\nconst forwarder = ForwarderFactory.getProxyForwarder(ChainID.MAINNET, ReplayProtectionType.MULTINONCE, signer);\n```\n\nThe above option configures the proxy accounts to use multi-nonce replay protection (with 30 nonce queues). If you want all transactions to be processed in the transaction by order, then just set `ReplayProtectionType.NONCE`.\n\nIf you want to use the RelayHub:\n\n```\nconst signer = wallet.Mnemonic(\"\");\nconst forwarder = ForwarderFactory.getRelayHubForwarder(ChainID.MAINNET, ReplayProtectType.BITFLIP, signer);\n```\n\nThe above configures the relay hub to use the bitflip replay protection. Bitflip supports an _unlimited number of concurrent transactions_ which is useful for batch withdrawals. It does not support ordered transactions, so use replace-by-nonce if you require ordering.\n\n5. You are now ready to authorise a meta-transaction using the ForwarderFactory.\n\n```\nconst user = Wallet.fromMnemonic(\"\");\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.broadcastMessage.encode([\"to the moon\"]);\nconst value = new BigNumber(\"0\");\n\nconst forwarder = ForwarderFactory.getProxyForwarder(ChainID.MAINNET, ReplayProtectionType.MULTINONCE, signer);\nconst data = {target: echo.address, value: value, callData: callData}; // Explicit tutorial\nconst params = await forwarder.signMetaTransaction({target: echo.address, value, data}) ;\n```\n\nThe forwarder just requires:\n\n- Target contract's address,\n- Value to be sent (proxy fowarder only)\n- Desired calldata (function name and its arguments).\n\nIt takes care of the replay protection (multinonce/bitflip) and authorising the meta-transaction under the hood. The returned `params` can be used to send the meta-transaction to Ethereum:\n\n```\nconst relayer = Wallet.fromMnemonic(\"\");\n\n// All meta-transactions for ProxyAccountFactory are sent from the user's ProxyAccount contract.\n// We assume it is already deployed on the network. Look at the ProxyAccountFactory section to\n// find out more (super-easy to deploy).\nconst proxyAccount = new ProxyAccountFactory(relayer).attach(params.to);\nconst tx = await proxyAccount\n        .connect(relayer)\n        .forward(\n          params.target,\n          params.value,\n          params.data,\n          params.replayProtection,\n          params.replayProtectionAuthority,\n          params.signature\n        );\n\n```\n\n### All done! Good work!\n\nHere is a full example:\n\n```\n// What contract and function do we want to execute? And who is the signer?\nconst user = Wallet.fromMnemonic(\"\");\nconst targetContract = new EchoFactory(user).attach(\"\");\nconst value = new BigNumber(\"0\");\nconst callData = targetContract.interface.functions.test.encode([]);\n\n// Prepare and authorise the meta-transaction\nconst forwarder = ForwarderFactory.getProxyForwarder(ChainID.MAINNET, ReplayProtectionType.MULTINONCE, signer);\nconst params = await forwarder.signMetaTransaction({ target: targetContract.address, value, callData }) ;\n\n// Relayer publishes transaction\nconst relayerWallet Wallet.fromMnemonic(\"\");\nconst encodedMetaTx = forwarder.encodeMetaTransaction(params);\nconst tx = await relayerWallet.sendTransaction( {to: params.to, data: encodedMetaTx}) );\nconst receipt = await tx.wait(1)\n```\n\nAs we can see in the above, it is easy for the user to craft and sign a meta-transaction for the target contract. The `params` (or its encoding) can be wrapped in an Ethereum transaction and sent to the blockchain.\n\n## ProxyAccount vs RelayHub\n\nAs we mentioned earlier, there are two solutions to the msg.sender problem.\n\n- **ProxyAccountDeployer**: Deploys a proxy account contract for the user with a deterministic address. All meta-transactions are sent via the user's proxy account.\n- **RelayHub**: There is no proxy account contracts. The RelayHub appends the signer's address onto the calldata that is sent to the target contract. It requires the target contract to support the \\_msgSender() standard.\n\nWhile the ProxyAccountDeployer works for all existing smart contracts, the RelayHub requires the target contract to support the \\_msgSender() standard. If supported, the RelayHub allows the signer's address to be the msg.sender in the target contract. Going forward, we hope that the RelayHub serves as a model and it can later become a precompile/a new opcode in Ethereum.\n\nNote, the one big difference between the ProxyAccountDeployer and the RelayHub is the forward() function. ProxyAccountDeployer lets the user set `value` of ETH that can be sent (e.g. the proxy account can have an ETH balance) in the meta-transaction. However, the RelayHub does not have a `value` argument and does not support sending ETH. See [this issue](https://github.com/anydotcrypto/metatransactions/issues/9) to find out why.\n\n### Proxy Hub\n\nIt is a central registry contract that is responsible for deploying proxy contracts (`ProxyAccount.sol`). Every proxy contract is destinated for a single user and it has a deterministic address via CREATE2. We use the [CloneFactory](https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol) to minimise storage overhead on the network.\n\nThere is only one function to care about:\n\n```\nconst user = Wallet.fromMnemonic(\"\");\nawait proxyDeployer.createProxyContract(user.address);\n```\n\nIt deploys a new `ProxyAccount` for the user and then stores a record of it in the ProxyAccountDeployer. Our ProxyAccount is a minimal contract that checks the user's signed the meta-transaction and the replay protection is valid. It only has two functions:\n\n- **DeployContract contracts**: Deploys a new smart contract with a deterministic address.\n\n```\nawait proxyAccount.deployContract(\n          initData: string, // Bytecode of the contract\n          replayProtection: string, // Encoding of replay protection (nonce1, nonce2)\n          replayProtectionAuthority: string, // Address (default is 0x00....)\n          signature: string // Signer's signature (address stored in proxy)\n        );\n\n```\n\n- **Forward**: Calls out to the target contract with the user's desired calldata.\n\n```\nawait proxyAccount.forward(\n        target: string, // Contract address\n        value: BigNumber, // ETH to send\n        data: string, // Calldata\n        replayProtection: string, // Encoding of replay protection (nonce1, nonce2)\n        replayProtectionAuthority: string, // Address (default is 0x00....)\n        signature: string // Signer's signature (address stored in proxy)\n);\n```\n\nLet's look at a full code example.\n\n```\n// Who is our signer?\nconst user = Wallet.fromMnemonic(\"\");\nconst relayer = Wallet.fromMnemonic(\"\");\n\n\n// Deploying a smart contract\nconst echoFactory = new EchoFactory(user);\nconst initCode = echoFactory.getDeployTransaction().data! as string; // Constructor arguments accepted\n\n// Set up meta-transaction handler and sign meta-deployment\nconst forwarder = ForwarderFactory.multinonce(ChainID.MAINNET, ContractType.PROXYACCOUNTDEPLOYER, 100);\nconst params = await forwarder.signMetaDeployment(user, initCode);\n\n// Send to the network via the ProxyAccount sends transaction to network (or sent up to Relayer API)\n// Fetch the proxy account\nconst encodedMetaDeployment = forwarder.encodeMetaDeployment(params);\nconst tx = await relayer.sendTransaction({to: params.to, data: encodedMetaDeployment});\n\n// Compute deterministic address for the deployed contract (helper function coming soon)\nconst hByteCode = arrayify(keccak256(initCode));\nconst encodeToSalt = defaultAbiCoder.encode([\"address\", \"bytes\"],[signer.address, params.replayProtection]);\nconst salt = arrayify(keccak256(encodeToSalt));\nconst echoAddress = await proxyAccount.connect(relayer).computeAddress(salt, hByteCode);\n\n// Fetch the echo contract\nconst echoContract = echoFactory.attach(echoAddress);\n\n// Sending the meta-transaction\nconst callData = echoContract.interface.functions.broadcastMessage.encode([]);\nconst value = new BigNumber(\"0\");\nconst params = await forwarder.signMetaTransaction(\n        {to: echoContract.address,\n        value,\n        callData}\n      );\n\n// Send to Ethereum (or send up to the RelayerAPI)\nconst tx = proxyAccount.connect(relayer).forward(\n        params.target,\n        params.value,\n        params.data,\n        params.replayProtection,\n        params.replayProtectionAuthority,\n        params.signature\n);\n```\n\n### Relay Hub\n\nIt is a central registry contract that keeps track of the signer's address and the state of their replay protection. It can only be used with smart contracts that support the \\_msgSender() standard and inherit [MsgSender](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/account/MsgSender.sol). The global singleton [RelayHub](https://etherscan.io/address/0x70107abb312db18bd9addec39ce711374b09ebc1) must be hard-coded into the target contract. We hope it will become a standard that has community support & it can be included in all new contracts.\n\nThe benefit of the RelayHub is that the signer's address is set as the msg.sender and there are no proxy contracts. Thus, it is more natural for the user who wants to look up their address in the contract. We hope our RelayHub will eventually become a new precompile or opcode in Ethereum - which may ultimately solve the msg.sender problem for relay transactions.\n\nIt only has two functions:\n\n- **DeployContract contracts**: Deploys a new smart contract with a deterministic address.\n\n```\nawait relayHub.deployContract(\n          initData: string, // Bytecode of the contract\n          replayProtection: string, // Encoding of replay protection (nonce1, nonce2)\n          replayProtectionAuthority: string, // Address (default is 0x00....)\n          signature: string // Signer's signature (address stored in proxy)\n        );\n```\n\n- **Forward**: Calls out to the target contract with the user's desired calldata. The signer's address is appended to the calldata sent to the target contract.\n\n```\nawait relayHub.forward(\n        target: string, // Contract address\n        data: string, // Calldata\n        replayProtection: string, // Encoding of replay protection (nonce1, nonce2)\n        replayProtectionAuthority: string, // Address (default is 0x00....)\n        signature: string // Signer's signature (address stored in proxy)\n);\n```\n\nHere is a code example for both:\n\n```\n// Who is our signer?\nconst user = Wallet.fromMnemonic(\"\");\nconst relayer = Wallet.fromMnemonic(\"\");\n\n// Deploying a smart contract\nconst echoFactory = new EchoFactory(user);\nconst initCode = echoFactory.getDeployTransaction().data! as string; // Constructor arguments accepted\n\n// Set up meta-transaction handler and sign meta-deployment\nconst forwarder = ForwarderFactory.multinonce(ChainID.MAINNET, ContractType.RELAYHUB, 100);\nconst params = await forwarder.signMetaDeployment(user, initCode);\n\n// Relayer sends transaction to network\nconst relayHubAddress = ForwarderFactory.getHubAddress(ChainID.MAINNET, ContractType.RELAYHUB);\nconst relayHub = new RelayHubFacotry(relayer).attach(relayHubAddress);\nconst tx = await relayHub.connect(relayer).deployContract(\n          params.data,\n          params.replayProtection,\n          params.replayProtectionAuthority,\n          params.signature\n        );\n\n// Compute deterministic address for the deployed contract (helper function coming soon)\nconst hByteCode = arrayify(keccak256(initCode));\nconst encodeToSalt = defaultAbiCoder.encode([\"address\", \"bytes\"],[signer.address, params.replayProtection]);\nconst salt = arrayify(keccak256(encodeToSalt));\nconst echoAddress = await relayHub.connect(relayer).computeAddress(salt, hByteCode);\n\n// Fetch the echo contract\nconst echoContract = echoFactory.attach(echoAddress);\n\n// Sending the meta-transaction\nconst callData = echoContract.interface.functions.broadcastMessage.encode([]);\nconst value = new BigNumber(\"0\");\nconst params = await forwarder.signMetaTransaction(\n        user,\n        echoContract.address,\n        value,\n        callData\n      );\n\n// Send to Ethereum (or send up to the RelayerAPI)\nconst tx = relayHub.connect(relayer).forward(\n        params.target,\n        params.data,\n        params.replayProtection,\n        params.replayProtectionAuthority,\n        params.signature\n);\n```\n\n## How to build and test the library locally\n\nWe need to install the NPM packages:\n\n```\nnpm i\n```\n\nThen we can simply build and test:\n\n```\nnpm run build && npm run test\n```\n\n## Where is the ProxyAccountFactory and RelayHub?\n\nWe have deployed the latest version of the ProxyAccountFactory and RelayHub. The links can be found below.\n\nMainnet:\n\n- [ProxyAccountFactory](https://etherscan.io/address/0xE139c086d9EEC16cBaF5a125FFf748939Fb734f1)\n- [RelayHub](https://etherscan.io/address/0x36892A63E99d66d01766e227F3cCc6235dE09eD9)\n\nRopsten:\n\n- [ProxyAccountFactory](https://ropsten.etherscan.io/address/0x5A60af44A45d11Cefd0182cb0514cce3149a0445)\n- [RelayHub](https://ropsten.etherscan.io/address/0xf4cb3Ff902f8fE23f3638Eb6F33B467c4180e605)\n\nThanks for checking out this code repository. It was first motivated by EIP-2585 and the RelayHub standard by the GSN.\n","readmeFilename":"README.md","gitHead":"0fac20da6b8db1d36c68d8644bccaf5e8237af0a","_id":"@anydotcrypto/metatransactions@0.0.11-2","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-qiHJJUspEqispSrj3nJzqKCGdMyqus5PgZFxcxPCLe0ZYzIV6ZeD5Fr5Bd0onAuDFCCTs5YC1JeKfLa4wruyYw==","shasum":"1bb8bfa014dd9cd5bcd18c2278aebc76391ecda3","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.11-2.tgz","fileCount":85,"unpackedSize":516185,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJesWPoCRA9TVsSAnZWagAAzvMQAIwe187543wzIHjb6o62\nCeByeV9nIIbzYccjkTlQK+3y5PwIlXXUhZ+5qDR28YnAFsTUja8+S/mJWG11\noIdJfw7oZDRafY+ZbqXjfgkOsGptrF3Kguy5T3qj0JEYCxqqOa0vXiWOAweJ\ntcJRcNa1d1GAawWbxnF+RKTpBojekhotF/cRNif/VXlF9xy2yMG8Vz+WGFLV\n18QspviGnQGTnyWcI2g9AmteX8jREtCO0LfleIdeFpfnDfmFLYu4s3OtBdez\ns8lu3MatPLteOH6L5JXpN/rMAO/SSU3L2/t3IgKYBkiOYSaqkCM52sDlc6/n\n7w9fEzYvWZUi+LtDgDZ0L1efDuENuqGwT/SuikDC4RAbM5+wRIMaosibnCt+\ncDE39RKIXWwYa32clElVvnKj1Y/4MrtzPDrgFvFE+eO3Ajt+BfhKKxTQtzEB\nb3GygJuBqIXku0WunH8WiMe1+z5LNWveGR8RgpLVBdo1R4v/N1BxAXeYPF67\nsFye8mA14p29+bd7P96wZ27VT10leiw0Eyb4r/M/P+PsHrRz8TVZXegB9i/T\nH/himMIgG/wug0g5E8QROzmesFCz46ETrZHwb7xlrzyb6uCwwVGp8x82DNe6\n3UC7MU7Bu3Dq/1KxocP8Bq7CYXTE4Jp9OOdIhYCICtGL88SQd3BrsWvF24Gs\nr2VD\r\n=AeZE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBbGqtYpWKqFJ/Zo3kh9F5P0kcTxktjy6i5Y3QMZg3KmAiEA/p00EyLoDpEKACvm+oxJ02xyHahOuAEkaqbqs5HQu/8="}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.11-2_1588683752341_0.4600467674154902"},"_hasShrinkwrap":false},"0.0.11-3":{"name":"@anydotcrypto/metatransactions","version":"0.0.11-3","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dit/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts && tsc -p tsconfig.json && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -r ./dist && rm -r ./build","prepublishOnly":"npm run clean && npm run build"},"devDependencies":{"@pisa-research/utils":"^0.1.39","@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","np":"^6.2.1"},"dependencies":{"@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","bn.js":"^5.1.1","ethers":"^4.0.43","npm":"^6.14.4","secure-random":"^1.1.2","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contracts:** All transactions for the user are sent via a proxy contract and it is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a global RelayHub.sol contract and the target contract must support the standard which requires it to replace msg.sender with \\_msgSender(). It is only compatible with contracts that have upgraded to use the standard.\n\nWe have put together this meta-transaction library to support both approaches. We hope it will benefit the community in the following ways:\n\n- **Ease of adoption:** All new smart contracts can support meta-transactions without handling replay protection (e.g. the permit() standard).\n- **Global RelayHub:** Our minimal RelayHub.sol can be a candidate for the hard-coded RelayHub in the \\_msgSender() standard.\n- **Single client library:** There are several libraries for constructing and signing transactions, but more often than not it is mixed up with the application logic. This repository is designed to become a single standard any project can adopt.\n\nFinally, the ultimate goal is to make it easier for developers to tap into third party relayer APIs that focus on getting transactions in the blockchain.\n\n## Getting started\n\nWe assume you have already set up your environment and you simply need to plug-in our library.\n\n1. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. You need to import the package into your file:\n\n```\nimport { ChainID, ReplayProtectionType, ForwarderFactory } from \"@anydotcrypto/metatransactions/dist\";\n```\n\n3. You need to decide which the network, replay protection, and the msg.sender solution.\n\nWe have support for two networks:\n\n```\nChainID.MAINNET\nChainID.ROPSTEN\n```\n\nOur library contains three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Replace-by-nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nThe enumeration is simpe:\n\n```\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\nReplayProtectionType.MULTINONCE // N queues\nReplayProtectionType.NONCE // Single queue\n```\n\nFor the msg.sender solution, we cover [ProxyAccountFactory vs RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub) later in the README. If you are unsure which one to use, then we recommend `ContractType.PROXYACCOUNTDEPLOYER` as it works for all existing contracts. Essentially, each user has a minimal proxy account contract and their meta-transaction is sent via the proxy. The target's msg.sender is the proxy contract's address.\n\n4. Time to instantiate the forwarder library!\n\nIf you want to use Proxy Accounts:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst concurrency = 10;\nconst forwarder = ForwarderFactory.getProxyForwarder(ChainID.MAINNET, ReplayProtectionType.MULTINONCE, signer);\n```\n\nThe above option configures the proxy accounts to use multi-nonce replay protection (with 30 nonce queues). If you want all transactions to be processed in the transaction by order, then just set `ReplayProtectionType.NONCE`.\n\nIf you want to use the RelayHub:\n\n```\nconst signer = wallet.Mnemonic(\"\");\nconst forwarder = ForwarderFactory.getRelayHubForwarder(ChainID.MAINNET, ReplayProtectType.BITFLIP, signer);\n```\n\nThe above configures the relay hub to use the bitflip replay protection. Bitflip supports an _unlimited number of concurrent transactions_ which is useful for batch withdrawals. It does not support ordered transactions, so use replace-by-nonce if you require ordering.\n\n5. You are now ready to authorise a meta-transaction using the ForwarderFactory.\n\n```\nconst user = Wallet.fromMnemonic(\"\");\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.broadcastMessage.encode([\"to the moon\"]);\nconst value = new BigNumber(\"0\");\n\nconst forwarder = ForwarderFactory.getProxyForwarder(ChainID.MAINNET, ReplayProtectionType.MULTINONCE, signer);\nconst data = {target: echo.address, value: value, callData: callData}; // Explicit tutorial\nconst params = await forwarder.signMetaTransaction({target: echo.address, value, data}) ;\n```\n\nThe forwarder just requires:\n\n- Target contract's address,\n- Value to be sent (proxy fowarder only)\n- Desired calldata (function name and its arguments).\n\nIt takes care of the replay protection (multinonce/bitflip) and authorising the meta-transaction under the hood. The returned `params` can be used to send the meta-transaction to Ethereum:\n\n```\nconst relayer = Wallet.fromMnemonic(\"\");\n\n// All meta-transactions for ProxyAccountFactory are sent from the user's ProxyAccount contract.\n// We assume it is already deployed on the network. Look at the ProxyAccountFactory section to\n// find out more (super-easy to deploy).\nconst proxyAccount = new ProxyAccountFactory(relayer).attach(params.to);\nconst tx = await proxyAccount\n        .connect(relayer)\n        .forward(\n          params.target,\n          params.value,\n          params.data,\n          params.replayProtection,\n          params.replayProtectionAuthority,\n          params.signature\n        );\n\n```\n\n### All done! Good work!\n\nHere is a full example:\n\n```\n// What contract and function do we want to execute? And who is the signer?\nconst user = Wallet.fromMnemonic(\"\");\nconst targetContract = new EchoFactory(user).attach(\"\");\nconst value = new BigNumber(\"0\");\nconst callData = targetContract.interface.functions.test.encode([]);\n\n// Prepare and authorise the meta-transaction\nconst forwarder = ForwarderFactory.getProxyForwarder(ChainID.MAINNET, ReplayProtectionType.MULTINONCE, signer);\nconst params = await forwarder.signMetaTransaction({ target: targetContract.address, value, callData }) ;\n\n// Relayer publishes transaction\nconst relayerWallet Wallet.fromMnemonic(\"\");\nconst encodedMetaTx = forwarder.encodeMetaTransaction(params);\nconst tx = await relayerWallet.sendTransaction( {to: params.to, data: encodedMetaTx}) );\nconst receipt = await tx.wait(1)\n```\n\nAs we can see in the above, it is easy for the user to craft and sign a meta-transaction for the target contract. The `params` (or its encoding) can be wrapped in an Ethereum transaction and sent to the blockchain.\n\n## ProxyAccount vs RelayHub\n\nAs we mentioned earlier, there are two solutions to the msg.sender problem.\n\n- **ProxyAccountDeployer**: Deploys a proxy account contract for the user with a deterministic address. All meta-transactions are sent via the user's proxy account.\n- **RelayHub**: There is no proxy account contracts. The RelayHub appends the signer's address onto the calldata that is sent to the target contract. It requires the target contract to support the \\_msgSender() standard.\n\nWhile the ProxyAccountDeployer works for all existing smart contracts, the RelayHub requires the target contract to support the \\_msgSender() standard. If supported, the RelayHub allows the signer's address to be the msg.sender in the target contract. Going forward, we hope that the RelayHub serves as a model and it can later become a precompile/a new opcode in Ethereum.\n\nNote, the one big difference between the ProxyAccountDeployer and the RelayHub is the forward() function. ProxyAccountDeployer lets the user set `value` of ETH that can be sent (e.g. the proxy account can have an ETH balance) in the meta-transaction. However, the RelayHub does not have a `value` argument and does not support sending ETH. See [this issue](https://github.com/anydotcrypto/metatransactions/issues/9) to find out why.\n\n### Proxy Hub\n\nIt is a central registry contract that is responsible for deploying proxy contracts (`ProxyAccount.sol`). Every proxy contract is destinated for a single user and it has a deterministic address via CREATE2. We use the [CloneFactory](https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol) to minimise storage overhead on the network.\n\nThere is only one function to care about:\n\n```\nconst user = Wallet.fromMnemonic(\"\");\nawait proxyDeployer.createProxyContract(user.address);\n```\n\nIt deploys a new `ProxyAccount` for the user and then stores a record of it in the ProxyAccountDeployer. Our ProxyAccount is a minimal contract that checks the user's signed the meta-transaction and the replay protection is valid. It only has two functions:\n\n- **DeployContract contracts**: Deploys a new smart contract with a deterministic address.\n\n```\nawait proxyAccount.deployContract(\n          initData: string, // Bytecode of the contract\n          replayProtection: string, // Encoding of replay protection (nonce1, nonce2)\n          replayProtectionAuthority: string, // Address (default is 0x00....)\n          signature: string // Signer's signature (address stored in proxy)\n        );\n\n```\n\n- **Forward**: Calls out to the target contract with the user's desired calldata.\n\n```\nawait proxyAccount.forward(\n        target: string, // Contract address\n        value: BigNumber, // ETH to send\n        data: string, // Calldata\n        replayProtection: string, // Encoding of replay protection (nonce1, nonce2)\n        replayProtectionAuthority: string, // Address (default is 0x00....)\n        signature: string // Signer's signature (address stored in proxy)\n);\n```\n\nLet's look at a full code example.\n\n```\n// Who is our signer?\nconst user = Wallet.fromMnemonic(\"\");\nconst relayer = Wallet.fromMnemonic(\"\");\n\n\n// Deploying a smart contract\nconst echoFactory = new EchoFactory(user);\nconst initCode = echoFactory.getDeployTransaction().data! as string; // Constructor arguments accepted\n\n// Set up meta-transaction handler and sign meta-deployment\nconst forwarder = ForwarderFactory.multinonce(ChainID.MAINNET, ContractType.PROXYACCOUNTDEPLOYER, 100);\nconst params = await forwarder.signMetaDeployment(user, initCode);\n\n// Send to the network via the ProxyAccount sends transaction to network (or sent up to Relayer API)\n// Fetch the proxy account\nconst encodedMetaDeployment = forwarder.encodeMetaDeployment(params);\nconst tx = await relayer.sendTransaction({to: params.to, data: encodedMetaDeployment});\n\n// Compute deterministic address for the deployed contract (helper function coming soon)\nconst hByteCode = arrayify(keccak256(initCode));\nconst encodeToSalt = defaultAbiCoder.encode([\"address\", \"bytes\"],[signer.address, params.replayProtection]);\nconst salt = arrayify(keccak256(encodeToSalt));\nconst echoAddress = await proxyAccount.connect(relayer).computeAddress(salt, hByteCode);\n\n// Fetch the echo contract\nconst echoContract = echoFactory.attach(echoAddress);\n\n// Sending the meta-transaction\nconst callData = echoContract.interface.functions.broadcastMessage.encode([]);\nconst value = new BigNumber(\"0\");\nconst params = await forwarder.signMetaTransaction(\n        {to: echoContract.address,\n        value,\n        callData}\n      );\n\n// Send to Ethereum (or send up to the RelayerAPI)\nconst tx = proxyAccount.connect(relayer).forward(\n        params.target,\n        params.value,\n        params.data,\n        params.replayProtection,\n        params.replayProtectionAuthority,\n        params.signature\n);\n```\n\n### Relay Hub\n\nIt is a central registry contract that keeps track of the signer's address and the state of their replay protection. It can only be used with smart contracts that support the \\_msgSender() standard and inherit [MsgSender](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/account/MsgSender.sol). The global singleton [RelayHub](https://etherscan.io/address/0x70107abb312db18bd9addec39ce711374b09ebc1) must be hard-coded into the target contract. We hope it will become a standard that has community support & it can be included in all new contracts.\n\nThe benefit of the RelayHub is that the signer's address is set as the msg.sender and there are no proxy contracts. Thus, it is more natural for the user who wants to look up their address in the contract. We hope our RelayHub will eventually become a new precompile or opcode in Ethereum - which may ultimately solve the msg.sender problem for relay transactions.\n\nIt only has two functions:\n\n- **DeployContract contracts**: Deploys a new smart contract with a deterministic address.\n\n```\nawait relayHub.deployContract(\n          initData: string, // Bytecode of the contract\n          replayProtection: string, // Encoding of replay protection (nonce1, nonce2)\n          replayProtectionAuthority: string, // Address (default is 0x00....)\n          signature: string // Signer's signature (address stored in proxy)\n        );\n```\n\n- **Forward**: Calls out to the target contract with the user's desired calldata. The signer's address is appended to the calldata sent to the target contract.\n\n```\nawait relayHub.forward(\n        target: string, // Contract address\n        data: string, // Calldata\n        replayProtection: string, // Encoding of replay protection (nonce1, nonce2)\n        replayProtectionAuthority: string, // Address (default is 0x00....)\n        signature: string // Signer's signature (address stored in proxy)\n);\n```\n\nHere is a code example for both:\n\n```\n// Who is our signer?\nconst user = Wallet.fromMnemonic(\"\");\nconst relayer = Wallet.fromMnemonic(\"\");\n\n// Deploying a smart contract\nconst echoFactory = new EchoFactory(user);\nconst initCode = echoFactory.getDeployTransaction().data! as string; // Constructor arguments accepted\n\n// Set up meta-transaction handler and sign meta-deployment\nconst forwarder = ForwarderFactory.multinonce(ChainID.MAINNET, ContractType.RELAYHUB, 100);\nconst params = await forwarder.signMetaDeployment(user, initCode);\n\n// Relayer sends transaction to network\nconst relayHubAddress = ForwarderFactory.getHubAddress(ChainID.MAINNET, ContractType.RELAYHUB);\nconst relayHub = new RelayHubFacotry(relayer).attach(relayHubAddress);\nconst tx = await relayHub.connect(relayer).deployContract(\n          params.data,\n          params.replayProtection,\n          params.replayProtectionAuthority,\n          params.signature\n        );\n\n// Compute deterministic address for the deployed contract (helper function coming soon)\nconst hByteCode = arrayify(keccak256(initCode));\nconst encodeToSalt = defaultAbiCoder.encode([\"address\", \"bytes\"],[signer.address, params.replayProtection]);\nconst salt = arrayify(keccak256(encodeToSalt));\nconst echoAddress = await relayHub.connect(relayer).computeAddress(salt, hByteCode);\n\n// Fetch the echo contract\nconst echoContract = echoFactory.attach(echoAddress);\n\n// Sending the meta-transaction\nconst callData = echoContract.interface.functions.broadcastMessage.encode([]);\nconst value = new BigNumber(\"0\");\nconst params = await forwarder.signMetaTransaction(\n        user,\n        echoContract.address,\n        value,\n        callData\n      );\n\n// Send to Ethereum (or send up to the RelayerAPI)\nconst tx = relayHub.connect(relayer).forward(\n        params.target,\n        params.data,\n        params.replayProtection,\n        params.replayProtectionAuthority,\n        params.signature\n);\n```\n\n## How to build and test the library locally\n\nWe need to install the NPM packages:\n\n```\nnpm i\n```\n\nThen we can simply build and test:\n\n```\nnpm run build && npm run test\n```\n\n## Where is the ProxyAccountFactory and RelayHub?\n\nWe have deployed the latest version of the ProxyAccountFactory and RelayHub. The links can be found below.\n\nMainnet:\n\n- [ProxyAccountFactory](https://etherscan.io/address/0xE139c086d9EEC16cBaF5a125FFf748939Fb734f1)\n- [RelayHub](https://etherscan.io/address/0x36892A63E99d66d01766e227F3cCc6235dE09eD9)\n\nRopsten:\n\n- [ProxyAccountFactory](https://ropsten.etherscan.io/address/0x5A60af44A45d11Cefd0182cb0514cce3149a0445)\n- [RelayHub](https://ropsten.etherscan.io/address/0xf4cb3Ff902f8fE23f3638Eb6F33B467c4180e605)\n\nThanks for checking out this code repository. It was first motivated by EIP-2585 and the RelayHub standard by the GSN.\n","readmeFilename":"README.md","gitHead":"428e24ceebd3dc60ac55698e27b3055af2732fe0","_id":"@anydotcrypto/metatransactions@0.0.11-3","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-uq9NKjvCPNCEenqZfFtxuBIvoO+xOXPu/QsYZcVtREziddxYSY2rNaP2F2D2CDm8S3yuOZzoKnil4s2R5V4pSA==","shasum":"1de1726d5083629d06e858f60e691529311462f0","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.11-3.tgz","fileCount":85,"unpackedSize":516189,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJesXJeCRA9TVsSAnZWagAAFAcQAI7dfoTNI3xmQs/MkXLG\no1v+rWHHi/0e15SWeQFquzXOuWuTZ/7BJhUk5YSufXuuqfL6+HVTQ/cD5egM\nYfooXwT9MrjIuIZIlbKRAPyKASg/XJej+WoojAYWhGzLG1ILZDh2jlga1j73\nGEcPMoHbj/S2BzqtO4oDrKzXPhDqHepW2X0yEtHEIdM7fUrHpnaLb7TrIEor\nHkgmBW8FwNV4BRf6vvEZqV1wv39XcuCCAtcDXci4RlekpXnmcSJMuiDEQmBM\nraTaj11P8YJHa0tjzrsoHy4LgUugbdJ6nzm+9RhoN/4+mLbuFN8GZSyXWfBF\nDw1/AVqTXGqPww23BRG9t1imqy/Cjv0oJB+boVrfMf6L1AH8Hb+pxnnyxLZG\nJvxzeGOcrjtbzfM7TfFz7Z5hB+/QzOlHY734wgV7bXmEtYma6HRZ8TQ4GE8k\naFd921KFoI65BYE2pDlUg/d/Dm8efKsnQA+plqMYmj+5De/vjGCgtdkC9j/t\nu6fryZlyzV8X1sAzngRhmje3g+r62gtIZtU9p2R3EE4D8JpeMbt/BM2Q57AT\nZBw/hVoP/2s+EMn1QSvgTybDNPS8JYDWuMsGIx1+8jgrroc1vH9FebCH+19e\ndisb4ZYlnJRzGShzQIP8GwWVh2Q0EA4kmGuZug8AxXHAuI4ADoLdQznY6zn1\nBpHJ\r\n=tTuE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCLlN6oVTvLES4axkjYtCxb7W8yTT2Y2k0uAkLGThLqkQIhANdhWvJvh1+kn5jZjb05jsajv3LCGexFGs9CJE1sg6Mq"}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.11-3_1588687453400_0.24033014657995033"},"_hasShrinkwrap":false},"0.0.11-4":{"name":"@anydotcrypto/metatransactions","version":"0.0.11-4","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts && tsc -p tsconfig.json && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -r ./dist && rm -r ./build","prepublishOnly":"npm run clean && npm run build"},"devDependencies":{"@pisa-research/utils":"^0.1.39","@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","np":"^6.2.1"},"dependencies":{"@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@types/bn.js":"^4.11.6","bn.js":"^5.1.1","ethers":"^4.0.43","npm":"^6.14.4","secure-random":"^1.1.2","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contracts:** All transactions for the user are sent via a proxy contract and it is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a global RelayHub.sol contract and the target contract must support the standard which requires it to replace msg.sender with \\_msgSender(). It is only compatible with contracts that have upgraded to use the standard.\n\nWe have put together this meta-transaction library to support both approaches. We hope it will benefit the community in the following ways:\n\n- **Ease of adoption:** All new smart contracts can support meta-transactions without handling replay protection (e.g. the permit() standard).\n- **Global RelayHub:** Our minimal RelayHub.sol can be a candidate for the hard-coded RelayHub in the \\_msgSender() standard.\n- **Single client library:** There are several libraries for constructing and signing transactions, but more often than not it is mixed up with the application logic. This repository is designed to become a single standard any project can adopt.\n\nFinally, the ultimate goal is to make it easier for developers to tap into third party relayer APIs that focus on getting transactions in the blockchain.\n\n## Getting started\n\nWe assume you have already set up your environment and you simply need to plug-in our library.\n\n1. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. You need to import the package into your file:\n\n```\nimport { ChainID, ReplayProtectionType, ForwarderFactory } from \"@anydotcrypto/metatransactions/dist\";\n```\n\n3. You need to decide which the network, replay protection, and the msg.sender solution.\n\nWe have support for two networks:\n\n```\nChainID.MAINNET\nChainID.ROPSTEN\n```\n\nOur library contains three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Replace-by-nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nThe enumeration is simpe:\n\n```\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\nReplayProtectionType.MULTINONCE // N queues\nReplayProtectionType.NONCE // Single queue\n```\n\nFor the msg.sender solution, we cover [ProxyAccountFactory vs RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub) later in the README. If you are unsure which one to use, then we recommend `ContractType.PROXYACCOUNTDEPLOYER` as it works for all existing contracts. Essentially, each user has a minimal proxy account contract and their meta-transaction is sent via the proxy. The target's msg.sender is the proxy contract's address.\n\n4. Time to instantiate the forwarder library!\n\nIf you want to use Proxy Accounts:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst concurrency = 10;\nconst forwarder = ForwarderFactory.getProxyForwarder(ChainID.MAINNET, ReplayProtectionType.MULTINONCE, signer);\n```\n\nThe above option configures the proxy accounts to use multi-nonce replay protection (with 30 nonce queues). If you want all transactions to be processed in the transaction by order, then just set `ReplayProtectionType.NONCE`.\n\nIf you want to use the RelayHub:\n\n```\nconst signer = wallet.Mnemonic(\"\");\nconst forwarder = ForwarderFactory.getRelayHubForwarder(ChainID.MAINNET, ReplayProtectType.BITFLIP, signer);\n```\n\nThe above configures the relay hub to use the bitflip replay protection. Bitflip supports an _unlimited number of concurrent transactions_ which is useful for batch withdrawals. It does not support ordered transactions, so use replace-by-nonce if you require ordering.\n\n5. You are now ready to authorise a meta-transaction using the ForwarderFactory.\n\n```\nconst user = Wallet.fromMnemonic(\"\");\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.broadcastMessage.encode([\"to the moon\"]);\nconst value = new BigNumber(\"0\");\n\nconst forwarder = ForwarderFactory.getProxyForwarder(ChainID.MAINNET, ReplayProtectionType.MULTINONCE, signer);\nconst data = {target: echo.address, value: value, callData: callData}; // Explicit tutorial\nconst params = await forwarder.signMetaTransaction({target: echo.address, value, data}) ;\n```\n\nThe forwarder just requires:\n\n- Target contract's address,\n- Value to be sent (proxy fowarder only)\n- Desired calldata (function name and its arguments).\n\nIt takes care of the replay protection (multinonce/bitflip) and authorising the meta-transaction under the hood. The returned `params` can be used to send the meta-transaction to Ethereum:\n\n```\nconst relayer = Wallet.fromMnemonic(\"\");\n\n// All meta-transactions for ProxyAccountFactory are sent from the user's ProxyAccount contract.\n// We assume it is already deployed on the network. Look at the ProxyAccountFactory section to\n// find out more (super-easy to deploy).\nconst proxyAccount = new ProxyAccountFactory(relayer).attach(params.to);\nconst tx = await proxyAccount\n        .connect(relayer)\n        .forward(\n          params.target,\n          params.value,\n          params.data,\n          params.replayProtection,\n          params.replayProtectionAuthority,\n          params.signature\n        );\n\n```\n\n### All done! Good work!\n\nHere is a full example:\n\n```\n// What contract and function do we want to execute? And who is the signer?\nconst user = Wallet.fromMnemonic(\"\");\nconst targetContract = new EchoFactory(user).attach(\"\");\nconst value = new BigNumber(\"0\");\nconst callData = targetContract.interface.functions.test.encode([]);\n\n// Prepare and authorise the meta-transaction\nconst forwarder = ForwarderFactory.getProxyForwarder(ChainID.MAINNET, ReplayProtectionType.MULTINONCE, signer);\nconst params = await forwarder.signMetaTransaction({ target: targetContract.address, value, callData }) ;\n\n// Relayer publishes transaction\nconst relayerWallet Wallet.fromMnemonic(\"\");\nconst encodedMetaTx = forwarder.encodeMetaTransaction(params);\nconst tx = await relayerWallet.sendTransaction( {to: params.to, data: encodedMetaTx}) );\nconst receipt = await tx.wait(1)\n```\n\nAs we can see in the above, it is easy for the user to craft and sign a meta-transaction for the target contract. The `params` (or its encoding) can be wrapped in an Ethereum transaction and sent to the blockchain.\n\n## ProxyAccount vs RelayHub\n\nAs we mentioned earlier, there are two solutions to the msg.sender problem.\n\n- **ProxyAccountDeployer**: Deploys a proxy account contract for the user with a deterministic address. All meta-transactions are sent via the user's proxy account.\n- **RelayHub**: There is no proxy account contracts. The RelayHub appends the signer's address onto the calldata that is sent to the target contract. It requires the target contract to support the \\_msgSender() standard.\n\nWhile the ProxyAccountDeployer works for all existing smart contracts, the RelayHub requires the target contract to support the \\_msgSender() standard. If supported, the RelayHub allows the signer's address to be the msg.sender in the target contract. Going forward, we hope that the RelayHub serves as a model and it can later become a precompile/a new opcode in Ethereum.\n\nNote, the one big difference between the ProxyAccountDeployer and the RelayHub is the forward() function. ProxyAccountDeployer lets the user set `value` of ETH that can be sent (e.g. the proxy account can have an ETH balance) in the meta-transaction. However, the RelayHub does not have a `value` argument and does not support sending ETH. See [this issue](https://github.com/anydotcrypto/metatransactions/issues/9) to find out why.\n\n### Proxy Hub\n\nIt is a central registry contract that is responsible for deploying proxy contracts (`ProxyAccount.sol`). Every proxy contract is destinated for a single user and it has a deterministic address via CREATE2. We use the [CloneFactory](https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol) to minimise storage overhead on the network.\n\nThere is only one function to care about:\n\n```\nconst user = Wallet.fromMnemonic(\"\");\nawait proxyDeployer.createProxyContract(user.address);\n```\n\nIt deploys a new `ProxyAccount` for the user and then stores a record of it in the ProxyAccountDeployer. Our ProxyAccount is a minimal contract that checks the user's signed the meta-transaction and the replay protection is valid. It only has two functions:\n\n- **DeployContract contracts**: Deploys a new smart contract with a deterministic address.\n\n```\nawait proxyAccount.deployContract(\n          initData: string, // Bytecode of the contract\n          replayProtection: string, // Encoding of replay protection (nonce1, nonce2)\n          replayProtectionAuthority: string, // Address (default is 0x00....)\n          signature: string // Signer's signature (address stored in proxy)\n        );\n\n```\n\n- **Forward**: Calls out to the target contract with the user's desired calldata.\n\n```\nawait proxyAccount.forward(\n        target: string, // Contract address\n        value: BigNumber, // ETH to send\n        data: string, // Calldata\n        replayProtection: string, // Encoding of replay protection (nonce1, nonce2)\n        replayProtectionAuthority: string, // Address (default is 0x00....)\n        signature: string // Signer's signature (address stored in proxy)\n);\n```\n\nLet's look at a full code example.\n\n```\n// Who is our signer?\nconst user = Wallet.fromMnemonic(\"\");\nconst relayer = Wallet.fromMnemonic(\"\");\n\n\n// Deploying a smart contract\nconst echoFactory = new EchoFactory(user);\nconst initCode = echoFactory.getDeployTransaction().data! as string; // Constructor arguments accepted\n\n// Set up meta-transaction handler and sign meta-deployment\nconst forwarder = ForwarderFactory.multinonce(ChainID.MAINNET, ContractType.PROXYACCOUNTDEPLOYER, 100);\nconst params = await forwarder.signMetaDeployment(user, initCode);\n\n// Send to the network via the ProxyAccount sends transaction to network (or sent up to Relayer API)\n// Fetch the proxy account\nconst encodedMetaDeployment = forwarder.encodeMetaDeployment(params);\nconst tx = await relayer.sendTransaction({to: params.to, data: encodedMetaDeployment});\n\n// Compute deterministic address for the deployed contract (helper function coming soon)\nconst hByteCode = arrayify(keccak256(initCode));\nconst encodeToSalt = defaultAbiCoder.encode([\"address\", \"bytes\"],[signer.address, params.replayProtection]);\nconst salt = arrayify(keccak256(encodeToSalt));\nconst echoAddress = await proxyAccount.connect(relayer).computeAddress(salt, hByteCode);\n\n// Fetch the echo contract\nconst echoContract = echoFactory.attach(echoAddress);\n\n// Sending the meta-transaction\nconst callData = echoContract.interface.functions.broadcastMessage.encode([]);\nconst value = new BigNumber(\"0\");\nconst params = await forwarder.signMetaTransaction(\n        {to: echoContract.address,\n        value,\n        callData}\n      );\n\n// Send to Ethereum (or send up to the RelayerAPI)\nconst tx = proxyAccount.connect(relayer).forward(\n        params.target,\n        params.value,\n        params.data,\n        params.replayProtection,\n        params.replayProtectionAuthority,\n        params.signature\n);\n```\n\n### Relay Hub\n\nIt is a central registry contract that keeps track of the signer's address and the state of their replay protection. It can only be used with smart contracts that support the \\_msgSender() standard and inherit [MsgSender](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/account/MsgSender.sol). The global singleton [RelayHub](https://etherscan.io/address/0x70107abb312db18bd9addec39ce711374b09ebc1) must be hard-coded into the target contract. We hope it will become a standard that has community support & it can be included in all new contracts.\n\nThe benefit of the RelayHub is that the signer's address is set as the msg.sender and there are no proxy contracts. Thus, it is more natural for the user who wants to look up their address in the contract. We hope our RelayHub will eventually become a new precompile or opcode in Ethereum - which may ultimately solve the msg.sender problem for relay transactions.\n\nIt only has two functions:\n\n- **DeployContract contracts**: Deploys a new smart contract with a deterministic address.\n\n```\nawait relayHub.deployContract(\n          initData: string, // Bytecode of the contract\n          replayProtection: string, // Encoding of replay protection (nonce1, nonce2)\n          replayProtectionAuthority: string, // Address (default is 0x00....)\n          signature: string // Signer's signature (address stored in proxy)\n        );\n```\n\n- **Forward**: Calls out to the target contract with the user's desired calldata. The signer's address is appended to the calldata sent to the target contract.\n\n```\nawait relayHub.forward(\n        target: string, // Contract address\n        data: string, // Calldata\n        replayProtection: string, // Encoding of replay protection (nonce1, nonce2)\n        replayProtectionAuthority: string, // Address (default is 0x00....)\n        signature: string // Signer's signature (address stored in proxy)\n);\n```\n\nHere is a code example for both:\n\n```\n// Who is our signer?\nconst user = Wallet.fromMnemonic(\"\");\nconst relayer = Wallet.fromMnemonic(\"\");\n\n// Deploying a smart contract\nconst echoFactory = new EchoFactory(user);\nconst initCode = echoFactory.getDeployTransaction().data! as string; // Constructor arguments accepted\n\n// Set up meta-transaction handler and sign meta-deployment\nconst forwarder = ForwarderFactory.multinonce(ChainID.MAINNET, ContractType.RELAYHUB, 100);\nconst params = await forwarder.signMetaDeployment(user, initCode);\n\n// Relayer sends transaction to network\nconst relayHubAddress = ForwarderFactory.getHubAddress(ChainID.MAINNET, ContractType.RELAYHUB);\nconst relayHub = new RelayHubFacotry(relayer).attach(relayHubAddress);\nconst tx = await relayHub.connect(relayer).deployContract(\n          params.data,\n          params.replayProtection,\n          params.replayProtectionAuthority,\n          params.signature\n        );\n\n// Compute deterministic address for the deployed contract (helper function coming soon)\nconst hByteCode = arrayify(keccak256(initCode));\nconst encodeToSalt = defaultAbiCoder.encode([\"address\", \"bytes\"],[signer.address, params.replayProtection]);\nconst salt = arrayify(keccak256(encodeToSalt));\nconst echoAddress = await relayHub.connect(relayer).computeAddress(salt, hByteCode);\n\n// Fetch the echo contract\nconst echoContract = echoFactory.attach(echoAddress);\n\n// Sending the meta-transaction\nconst callData = echoContract.interface.functions.broadcastMessage.encode([]);\nconst value = new BigNumber(\"0\");\nconst params = await forwarder.signMetaTransaction(\n        user,\n        echoContract.address,\n        value,\n        callData\n      );\n\n// Send to Ethereum (or send up to the RelayerAPI)\nconst tx = relayHub.connect(relayer).forward(\n        params.target,\n        params.data,\n        params.replayProtection,\n        params.replayProtectionAuthority,\n        params.signature\n);\n```\n\n## How to build and test the library locally\n\nWe need to install the NPM packages:\n\n```\nnpm i\n```\n\nThen we can simply build and test:\n\n```\nnpm run build && npm run test\n```\n\n## Where is the ProxyAccountFactory and RelayHub?\n\nWe have deployed the latest version of the ProxyAccountFactory and RelayHub. The links can be found below.\n\nMainnet:\n\n- [ProxyAccountFactory](https://etherscan.io/address/0xE139c086d9EEC16cBaF5a125FFf748939Fb734f1)\n- [RelayHub](https://etherscan.io/address/0x36892A63E99d66d01766e227F3cCc6235dE09eD9)\n\nRopsten:\n\n- [ProxyAccountFactory](https://ropsten.etherscan.io/address/0x5A60af44A45d11Cefd0182cb0514cce3149a0445)\n- [RelayHub](https://ropsten.etherscan.io/address/0xf4cb3Ff902f8fE23f3638Eb6F33B467c4180e605)\n\nThanks for checking out this code repository. It was first motivated by EIP-2585 and the RelayHub standard by the GSN.\n","readmeFilename":"README.md","gitHead":"542980d45be15ab3e5146b9ca7ae33f303815250","_id":"@anydotcrypto/metatransactions@0.0.11-4","_nodeVersion":"11.10.1","_npmVersion":"6.14.4","dist":{"integrity":"sha512-rJrA3KJNaUUwfGMnP/d6xRfI1AMZohqpR0NwqiwwaxwG9MKHb1dDWf6sdU3vGbCKDB4jtl8fe94B1DT9nOLMqw==","shasum":"c7f01aa3e579638918ca692f17310eb0ac5f3047","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.11-4.tgz","fileCount":85,"unpackedSize":516092,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJesXp6CRA9TVsSAnZWagAANlIP/1zDmLEn6S29jzs8RBj4\ngkWZf9sue7u7ImkdQ1tf8MgGEgHC6NuE51cwHAR9lgN8EAhTjEO73kKO72LA\n/5XqjDfHCOMasg3dSdgelU1tGHX9tb3X6EQPUzzoDP24ofHDIni1Qk6z+VzR\nzPMi6OZR4VbG3ir3SBte0D2BkQeXZlfgY3vneQ7FDwMGQayRWZGI6c+Cmd5B\no50O2uRo/YVfV2MVDQTUChGfNbLwu4FhKiulyj3MIJwwUBHfmZzo0fUivqUb\nUZ30nMNADzZPDLuJC1mvxhDoWzSxAuV5Gq2ctoakBpz1v0pThlJ0ypv2OjgX\nHPPilTwmsJpCfCDUTZJOHJAZt1BcuX2l/TByuzGO7RzOmyeNhzrQqPgcUOWX\nRqeZMzmNV58rw6ltQSJeAhbfayWzC8dIdTDixpfM4OBpyZbxA26vOo09WTS2\nBkWheXyOK8iie0I3Ht8k7YwuaxnK/RMmh1GqGp5NFUtrkBb/iTffYjNjH/pX\nq20jbjCUerkVSssfOY6MIHUv8ICAtJvKxfv0RsWcsoooMdXECu/s4OcDv/Xh\nFBOkB/mYpuGITy3rxan7yGfjf8ABW+2mHV72GHfzeGZ0RjqdmUYv1AlxiXcu\nGFEd3MyRCbqGl0NghBQ9geFeOVFqIeqgUYiMzs/gCDB2B9tZVSjCIZOprDNm\nzZUj\r\n=Mirp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDIR9vaetbf6Wgs78pYXXOflHe+3gaWFDNZ9F74N0VnoAiEA5PDXC5pQPkyh6ytGFP/Hb+0DPI5+870op48Uxsd4fWw="}]},"maintainers":[{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.11-4_1588689529927_0.07086126698306128"},"_hasShrinkwrap":false},"0.0.11-10":{"name":"@anydotcrypto/metatransactions","version":"0.0.11-10","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build","prepublishOnly":"npm run clean && npm run build && npm run build-ts && npm run publish-contracts"},"devDependencies":{"@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","@types/bn.js":"^4.11.6","bn.js":"^5.1.1","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","np":"^6.2.1"},"dependencies":{"@chainlink/contracts":"0.0.3","@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/utils":"^0.1.39","@pisa-research/test-utils":"^0.1.36","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"gitHead":"a5c5aaefefa56cda8ad4438363aacd72e921ba45","readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.  \n- **\\_msgSender():** All transactions are sent via a single RelayHub  contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nThis meta-transaction library supports both approaches. We hope it benefits the community in the following way: \n\n- **Ease of adoption:** All smart contracts can support meta-transactions without explicitly handling replay protection (e.g. [implementing a permit() standard](https://github.com/makerdao/dss/blob/master/src/dai.sol#L117-L141)).\n- **A candidate RelayHub standard:** Our minimal RelayHub.sol can be a candidate for the hard-coded RelayHub in the \\_msgSender() standard.\n- **Minimal proxy contracts:** Our ProxyAccount contracts have minimal functionality (e.g. it can only .call() to a target contract) which makes them easy to audit, reason about and adopt.\n- **Better-than-Ethereum Replay Protection:** We have implemented Nonce, MultiNonce and BitFlip, so the developer can decide if they want to ordered transactions, multiple queues of transactions, or always out-of-order transactions. \n\nThere are several libraries for constructing and signing meta-transactions, but more often than not it is mixed up with the application logic. This repository is protocol and relayer-independent such that it can become a single standard any project can adopt. Hopefully it will make it easier easier for developers to tap into third party relayer APIs and thus no longer need to re-implement the wheel of building reliable transaction infrastructure. \n\n# Table of Contents\n\n- [Getting started](#getting-started)\n- [You are now ready to authorise a meta-transaction!](#you-are-now-ready-to-authorise-a-meta-transaction-)\n  * [Example Echo Contract](#example-echo-contract)\n  * [Proxy Account Contract](#proxy-account-contract)\n  * [RelayHub](#relayhub)\n- [ProxyAccount vs RelayHub](#proxyaccount-vs-relayhub)\n  * [Proxy Account Contract](#proxy-account-contract-1)\n    + [Deploying the proxy contract](#deploying-the-proxy-contract)\n    + [Sign and encode meta-transactions](#sign-and-encode-meta-transactions)\n    + [Sign and encode meta-deployments](#sign-and-encode-meta-deployments)\n  * [Relay Hub](#relay-hub)\n    + [MsgSender.sol](#msgsendersol)\n    + [Sign and encode meta-transactions](#sign-and-encode-meta-transactions-1)\n    + [Sign and encode meta-deployments](#sign-and-encode-meta-deployments-1)\n\n# Getting started\n\nWe assume you have already set up your environment and you simply need to plug-in our library.\n\n1. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. Deciding which network and replay protection to use. \n\nYou will need to import both the ChainID and Replay Protection into your code: \n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\nOur library currently supports MAINNET or ROPSTEN. \n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Replace-by-nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n```\n// ReplayProtection \nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. You need to decide which solution to msg.sender you want to use. \n\nFor the msg.sender solution, we cover [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub) later in the README. If you are unsure which one to use, then ***we recommend proxy account contracts as it works for all existing contracts***. \n\n4. Time to instantiate the meta-transaction library with your prefered options! \n\nTo instantiate the proxy account forwarder: \n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract. \n\nImportant: It will sign meta-transactions even if the proxy account contract does not exist on the blockchain (e.g. it is not yet deployed). As we will see, it is easy to send up a batch transaction to the relayer such that a single Ethereum transaction will meta-deploy the proxy account contract before executing the meta-transaction. So there is no waiting/setup process. \n\nTo instantiate the RelayHub forwarder: \n```\nconst signer = Wallet.Mnemonic(\"\");\nconst relayHubForwarder = new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.NONCE,\n    signer\n);\n```\nThere is a single instance of the RelayHub on each network and the forwarder links to it. All replay protection is handled by the RelayHub contract and there is no requirement to broadcast/setup in advance. Again, it only works if the target contract supports the  \\_msgSender() standard.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nWe will use the Echo smart contract for both examples: \n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## Proxy Account Contract\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\"); \nconst forwarder = new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the signer's proxy account contract (note: it is very easy to meta-deploy the proxy account contract alongside the first meta-transaction):\n\n```\nconst isProxyDeployed = await forwarder.isProxyContractDeployed();\nif (!isProxyDeployed) {\n    const encodedTx = await forwarder.createProxyContract();\n    \n    // For our example we mimic the relayer API with a relayer wallet. \n    const proxyTx = await relayer.sendTransaction({\n      to: encodedTx.to,\n      data: encodedTx.callData,\n    });\n    \n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nTo authorise a meta-transaction you must supply:\n- **Target** contract's address,\n- **Value** to be sent \n- **Calldata** the function name and its arguments\n\nWe show how to do that for proxy account contracts: \n\n```\n// Fetch the contract and the calldata. \nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: echo.address,\n    value: new BigNumber(\"0\"),\n    callData,\n});\n\nconst encodedMetaTx = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: encodedMetaTx,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Well done! \n\n## RelayHub\nLet's set up our forwarder and signer: \n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\"); \n\nconst forwarder = new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWhile there is no setup/deployment to perform for the signer. It is important that your target contract supports the \\_msgSender() standard. So let's modify the Echo contract to support the standard:\n\n```\npragma solidity ^0.6.2;\nimport \"https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/account/MsgSender.sol\";\n\ncontract Echo is MsgSender {\n    event Broadcast(address signer, string message);\n    \n    // In the future we will hard-code the RelayHub \n    // address into MsgSender.sol\n    constructor(address _relayHub) public {\n        relayHub = _relayHub;\n    }\n    function submit(string memory _message) public\n    {\n        address signer = _msgSender();\n        emit Broadcast(signer, _message);\n    }\n}\n```\nNow that the target-contract supports the \\_msgSender() standard, you must supply the following to authorise a meta-transaction: \n- **Target** contract's address,\n- **Calldata** the function name and its arguments\n\nUnlike proxy account contracts, the RelayHub does not yet support native transfers of ETH. Now that we have the necessary informaton let's send the meta-transaction via the RelayHub: \n```\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([message]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: cyberDiceCon.address,\n    callData,\n});\nconst encodedMetaTx = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst receipt = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: encodedMetaTx,\n});\n\nconst tx = await receipt.wait();\n```\nWell done!\n\n# ProxyAccount vs RelayHub\n\nAs we mentioned earlier, there are two solutions to the msg.sender problem.\n\n- **Proxy Contract Accounts**: Every user has a proxy contract with a deterministic address. All meta-transactions are sent via the user's proxy account. \n- **RelayHub**: There is no proxy account contracts. The RelayHub appends the signer's address onto the calldata that is sent to the target contract. It requires the target contract to support the \\_msgSender() standard.\n\nWhile proxy contract accounts works for all existing smart contracts, the RelayHub requires the target contract to support the \\_msgSender() standard. If supported, the RelayHub allows the signer's address to be the msg.sender in the target contract. Going forward, we hope that the RelayHub serves as a model and it can later become a precompile/a new opcode in Ethereum.\n\nNote, the RelayHub does not support holding or sending ETH. It is possible to store a balance for each signer, but we opted for a simple/minimalist RelayHub. Find out more at [this issue](https://github.com/anydotcrypto/metatransactions/issues/9) to find out why.\n\n## Proxy Account Contract\n\nThere are two contracts:\n- **Proxy Deployer:** Responsible for deploying all proxy account contracts. \n- **Proxy Account:** A proxy contract for a single user.\n\nThe motivation for a ProxyDeployer contract is to act as a global registry for all proxy contracts. It is only responsible for deploying proxy contract addresses and thanks to CREATE2 it ensures all signers have a deterministic proxy address. \n\nThe proxy account contract is responsible for acting as the user's identity to other smart contracts such that msg.sender is the proxy contract's address. Our forwarder library ```ProxyAccountForwarder``` has methods to support interacting with proxy contracts. \n\n### Deploying the proxy contract\n\nWe must check if the proxy contract is deployed before deciding to deploy it. \n```\nconst isDeployed: boolean = await forwarder.isContractDeployed();\nconst encodedTx: EncodedTx = await forwarder.createProxyContract();\n```\nThe EncodedTx has the following interface:\n```\ninterface EncodedTx {\n  to: string; // Target contract address\n  data: string; // Calldata for the target contract\n  gas: number; // Estimate gas limit (work-in-progress)\n}\n```\nIt costs approximately ~110k gas (including transaction overhead) to deploy a proxy contract.\n\n### Sign and encode meta-transactions \n\nOur library supports signing and encoding the meta-transaction:\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nThe forward parameters has the following interface:\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address \n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Value in WEI to send\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection \n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. If desired, the forward parameters can be used to directly send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).forward(\n    params.target,\n    params.value,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it may be simpler to encode and send the meta-transaction:\n\n```\n// Encode calldata for ProxyAccount.forward() \nconst encodedMetaTx: EncodedTx = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: encodedMetaTx});\n```\n\n### Sign and encode meta-deployments \n\nA very exciting feature for our library is to support meta-deployments as the proxy contract will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract \n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata: \n\n```\n  const encodedMetaDeployment = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: encodedMetaDeployment,\n  });\n```\n\nBut what about the new contract address? How do we derive it? \n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\nWell done! You have leveled up and you can now perform meta-deployments! \n\n## RelayHub\n\nThe RelayHub has a single deployed contract on the network and it is available for all users. \n\nOne way to think about the RelayHub is that it emulates the Ethereum account system. It is only responsible for keeping track of a user's replay protection and verifying their signature. If both conditions pass, then it will append the signer's address to the target contract calldata before forwarding it. \n\nAs we have mentioned several times, the RelayHub is only compatible with contracts that support the \\_msgSender() standard. But the advantage of the RelayHub is that the signer's address is the msg.sender and there is no need to deploy a user-specific contract in advance. \n\n### MsgSender.sol \n\nThe target contract must extend MsgSender.sol and include the contract address of our RelayHub. Let's have a quick look at its code:\n\n```\npragma solidity 0.6.2;\ncontract MsgSender {\n    address public relayHub;\n    function _msgSender() internal view virtual returns (address payable) {\n        if (msg.sender != relayHub) {\n            return msg.sender;\n        } else {\n            return _getRelayedCallSender();\n        }\n    }\n\n    function _getRelayedCallSender() private pure returns (address payable result) {\n        bytes memory array = msg.data;\n        uint256 index = msg.data.length;\n        assembly {\n            result := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)\n        }\n        return result;\n    }\n}\n```\n\nWhen the RelayHub forwards a call to the target contract it will append the signer's address to the msg.data. So the target contract can simply verify that msg.sender is the RelayHub contract address and then extract the signer's address from the msg.sender. It will return the signer's address to the main contract. \n\nThus the target contract must replace msg.sender with \\_msgSender():\n\n```\naddress signer = _msgSender(); \n```\n\nThe original idea for msgSender originates from the gas station network (OpenGSN) and we hope to work together with them to standardise the RelayHub.sol. \n\n### Sign and encode meta-transactions\n\nOur library supports signing and encoding the meta-transaction:\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nThe forward parameters has the following interface:\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address \n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Always set to 0 for the RelayHub\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection \n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. Although it must be mentioned that ```value=\"0``` as the RelayHub does not support transfering ETH. If desired, the forward parameters can be used to send directly to the relayhub: \n\n```\nconst tx = await relayHubContract.connect(relayer).forward( \n    params.target,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n)\n```\n\nOf course, it may be simpler to encode and send the meta-transaction: \n\n```\n// Encode calldata for RelayHub.forward() \nconst encodedMetaTx: EncodedTx = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: encodedMetaTx});\n```\n\n\n### Sign and encode meta-deployments \n\nA very exciting feature for our library is to support meta-deployments as the RelayHubt will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract \n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the RelayHub:\n\n```\nconst tx = await relayHubContract.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata: \n\n```\n  const encodedMetaDeployment = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: encodedMetaDeployment,\n  });\n```\n\nBut what about the new contract address? How do we derive it? \n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\n^^ and that's all for now folks! ","readmeFilename":"README.md","_id":"@anydotcrypto/metatransactions@0.0.11-10","_nodeVersion":"11.14.0","_npmVersion":"6.13.1","dist":{"integrity":"sha512-befmezbT4k+DynSOKfhoG4DPBv7tJHkAvoZ9NRvMQIjIVM6Pc8r/cl29Qnjt9Ftf1DysKpWkeMhbRDnIjLbp7Q==","shasum":"815ae943350e47aaec51fa033134c9d58acc26ef","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.11-10.tgz","fileCount":100,"unpackedSize":513740,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJetWZPCRA9TVsSAnZWagAAtJMP/jKl8hhMJiIdiFlWMGUF\nXq1kdRBYg3axaEmVgDetq9TbrwM+s6pZtCv+l6nViHtMMj0VfzIYIdaPtKe6\nzlrRTl87sdbFBs/d1ZnMF9/P6HRZ+opIktiBpVULIn4XEctnUJXENx+14csW\nA5gwR4QfiXtJWBBMtbupzpgTw0TZiuZcd2MYaV6Rpgmk6wXvw6yOwcvfBWMm\npejwce/MWVek8fR0w/0i5d4Ycb5exGbjjpwUxrR2yVEe9jyElIwmeORzPZff\nF0TPMLJd3LoAASq230/+6W9Nb6USrYOSv/0toCgg3GW/c5rdBnCsCwDd5pq0\ne+LldBXJNoiKEESEjqWHgzva3nWcaUTDHjdcS0u8ZpdCNYF4VaX7XRhvdNR4\n7cqO/UFpYd24rg3/JLA/4k/F13dL3/L0fjTtsCFlYaCNWQu8ccbutcjBGQtt\n+p4LO42YR0Kvx4tJgdx4MxxSAyGsD1oYY8LUKomH5SXDocF3P+VPAkPmmuVh\nb0yHx3KpWVf5QrORYryB6K6LG/XqpcCUcZOEfravrfTkuaWxPxYDCUPq46+9\nBr3uwmbQ+TPPizVZ/+gUdk1Oad8csx2nMXTSGnyuCJ1IkZoJtjrRyp1hnX9A\nPr2GWiTnIwxCNIVL5jCJCrxjwSBTLGB29H0HqB+N+sgSnN5frD5bH3gk4VZ4\nPovc\r\n=g9Mx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCxezSY8fU4frzF6kR7z6FQKlm13yW7U05GwauPtYk1nAIgAUv7lH1xsxJ5cTOewfYSK5xCEpUiWMv7Z3aL36k1VO0="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"yahgwai","email":"cpbuckland88@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.11-10_1588946510634_0.5032322105403524"},"_hasShrinkwrap":false},"0.0.11":{"name":"@anydotcrypto/metatransactions","version":"0.0.11","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build","prepublishOnly":"npm run clean && npm run build && npm run build-ts && npm run publish-contracts"},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/chai-as-promised":"^7.1.2","@types/mocha":"^5.2.7","bn.js":"^5.1.1","chai":"^4.2.0","chai-as-promised":"^7.1.1","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/utils":"^0.1.39","@pisa-research/test-utils":"^0.1.36","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"gitHead":"929bb003ab71386bf0de0bea01370e4ab6f95c53","_id":"@anydotcrypto/metatransactions@0.0.11","_nodeVersion":"11.14.0","_npmVersion":"6.13.1","dist":{"integrity":"sha512-LlTV8R1qBB34s0VoP6lv14m6/xwJ7Lomf2kTgj7iADTovcjyfpGwM2YeGHk7L/5IhXRSqE/hyBlyIRQZACowyw==","shasum":"e176ecc5b69f098bc6b52c712a7753b31ed0f8b5","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.11.tgz","fileCount":97,"unpackedSize":511619,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeutkFCRA9TVsSAnZWagAAtpoP+gNnAYhDIzLiwkGTNQvh\nolBaqwbYSzNOV9dh+1Ro1JKlS4q6/r4/Vp4T7rSJcQ/DNdstscaZuAfT6Kby\n4KyqF1eAy/v+xIbZTkh2nM+Y80B3YixGCwsoyqupV4ohpCmodozxsfrC7To6\nwsQRHDGzmbCJ6TYPC9ydatNzsptoJcoldgLRiaZOQWKm9C47JNq7FG+aQFz0\naNV+kXYRogkPl11Kwkm3+ZXD6o49TtoGL++L0gyzNjZIZ0fnGShyRDVCItfQ\nLuj/fWqGAL/Caxf8apQSKC+T8I6C4LkgtL4tK6/w5agKF5U2BjOKfjE4O8Q+\nqVZNQDdx8kVRe/A5yoOavHAMXhIsyWdfZDNhUH+iXWcaFBfRrLVnl+MK484k\nZ2W+WGphhaVXHHadSeLiPuWXkIK35Nwp8Ug+6chOp9JI0HKaP9o0voxdNxcN\n7BIx9RvT0DBoZdqESMztUiYugcLhauc4QmbkLFocW31jRWD6vTkhlAla302V\nDNs+CfD1T1d9BzTcuInQnp/APiV2IHmNWpetmighMd+uE9IMlMdtsLCoifP6\ny84oCV+2lagSvhx9i1/uAI0irbSJMTNswVmjxBJ6idVUxTaBVsHyrctnKR8+\n6jYbNOzY9QM60iV0I/unZpNc1hy0L5cm1hYszh3n0esp/C84JEkb4NRqfK8D\nwMp4\r\n=ereT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC9CEu8ccTxkgsibTzjbCfUgx8tJ0lAx6xe0yjsKplDrAiEA+cKQmCpId+9GgEbu5JYuRwWWgwv+53DNoXYfk+h/QI8="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"yahgwai","email":"cpbuckland88@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.11_1589303557135_0.8882403083787602"},"_hasShrinkwrap":false},"0.0.12":{"name":"@anydotcrypto/metatransactions","version":"0.0.12","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build","prepublishOnly":"npm run clean && npm run build && npm run build-ts && npm run publish-contracts"},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/utils":"^0.1.39","@pisa-research/test-utils":"^0.1.36","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"gitHead":"f67db37a3f3b7419a8bb156f613789f81dbb6652","_id":"@anydotcrypto/metatransactions@0.0.12","_nodeVersion":"11.14.0","_npmVersion":"6.13.1","dist":{"integrity":"sha512-zoOn7ZTjam1cCAs0TFNkD41VFC08XGuGYQaYV+1adQzj/mdHK6XImE+1sNCL4NU7jTbesP6/kEmmuDV6SQMKXg==","shasum":"6b38ec2423ab9f0a8d77e18a0e357c4c11483be4","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.12.tgz","fileCount":100,"unpackedSize":515661,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJevW0/CRA9TVsSAnZWagAA1lYP/jExeUeV9D9UzLDvRj5e\nRk+7K18t7n/DLUnBlcAuuQf0Y0AxcFBVkCC7+k0rFa778vWXTnwmb8eD6J1c\n6iR72lUf9LNnxCJYJzJFExOv9I5pDYhPBKSOecXQEsvbQK6FXAxx2BTmzWze\nBphkctID9fuITnLmIxrU9zGf+qehr8/UZUqjO1WSDBreFHffadXKBYVcj2Tt\n0Gpe77qD5sGDdVXmAzFSCjBnBd5OKexMtgcf8IsjI8j6wJ04uLPuBlWujGbB\npN9As7uaDGjoiPN66bdOlkKXAX3cwq8ztj0fIRW49mvKXJSd41eDBvKSG53L\npH9olIQwfQzzPADnJo9GSWTCKvaSPWgW92yZkax7RTdDAz+y8PToJZlDJtdz\nQ6qh52LoDfdrvr3EfZfN+iWut1EQZwaAitX2bjLgrKPagUQAU5SqT23qSYjp\nU1baQYWyVJvwVUZVqYUv8s2IkNGi3TaOTFuRh9pQJ+0iSH/TrcY3hE4Tkil7\n3Cea8W4eAMRO5JI9Dn2lI645jO0bXJUbTR9gGuic2LPzT1O/w+GjJOsIpBz6\nVwnHYMf4Q2xCLDtOXdkJ6faQv4poM68zGJV6Inu8KXPbTM52c0vbBTZbZ6XR\n/0F9bgu75P/uyxmJ8YPP/Jz2y1n3T59+ATDUyBzw1++mdITHfVTp+ubv/cym\nExc9\r\n=c1BJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDv6sPKdzn7XzhDxJZ7Wnofx67+qA+nhiqayS3bCVuLRQIgN4/4rC38XaaqPkMQ0/wmuDQB0hWIr/d5YF/3vPr4/aY="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"yahgwai","email":"cpbuckland88@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.12_1589472575018_0.3128414035809375"},"_hasShrinkwrap":false},"0.0.13-0":{"name":"@anydotcrypto/metatransactions","version":"0.0.13-0","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build","prepublishOnly":"npm run clean && npm run build && npm run build-ts && npm run publish-contracts","preinstall":"node -e \"!process.env.npm_config_user_agent.startsWith('pnpm/') && !console.log('Install pnpm globally using \\`npm i -g pnpm\\` then do \\`pnpm i\\` to install dependencies in this repository\\n') && process.exit(1)\"","preuninstall":"node -e \"!process.env.npm_config_user_agent.startsWith('pnpm/') && !console.log('Install pnpm globally using \\`npm i -g pnpm\\` then do \\`pnpm i\\` to install dependencies in this repository\\n') && process.exit(1)\""},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/utils":"^0.1.39","@pisa-research/test-utils":"^0.1.36","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"gitHead":"a89bef7ce8a5ccae10d2fc6e915f77d5e71a0c27","_id":"@anydotcrypto/metatransactions@0.0.13-0","_nodeVersion":"11.14.0","_npmVersion":"6.13.1","dist":{"integrity":"sha512-LivXDVoV5siNM8VrbXFVkCqJ3BAErhOiDTmh1CczQQSyjHd2F4kb5LSGQqSghEp9jniQFAMw4Ix6dIYJn6Xx6w==","shasum":"5cf2a19e0fec46c07c6594ffaf47d8857e9f5ca9","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.13-0.tgz","fileCount":106,"unpackedSize":616197,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJevbBBCRA9TVsSAnZWagAAf9EP/jAnFKC/3GXBFWvheu34\nM7pQnCUVp4SR54A2NMAtEOFSlpKMukQHHuk2YaXGl22f7KVtPEivirI56rIn\ncV1ZkXZMOnXC+uzO6uIkWRCWGvhv14ZlCnY0w6a6FQWQ+wTJ/+Rpk0YcfcWa\ne42drNKuYFGSXn3Ze5IQ7yemPctaobx4oY/iLcteBoOIDSfyodQqcYOtszZw\nQlcVLz3xT/CzSgpESCijFMz1yuu6f9hDqT6HU9NanQn7sESaoaPzewYZOe5X\n6Q/oFzhjRT2yks5Ob5/sxBUPnvJt+hYjJmmyrx8jDLrLxg/gN3x32SXK0dDB\nbq1Wbuxyo5gjojx6jt2ITiCibIzNzg9clFHElW+ULi13UMgPU2yc/X6rOdbv\nT+TLXV8uObOWnv6GvWnR7m9jLX9mm7O0yOedprIYlxO0wAoGihO+kDL4YDZB\ndcxg8tkx2V7+CgozpUGVUWS0YfAYekxdbi/miNfPkEyi+koR9zxqgRyXkzRg\nWwh6d2tdSiL+0cSkV32e8aFeJmwQPDcPKYnK7KGRCBHOEbbbukaS4KTabToX\niQbG3A9ele2g3VS0GnOoOrQyxeoa4gPMfaih5lgS9cbm5O7G2TEFs/d+1Wc2\n2Go13WcRfRp17YlJT4ESfBuq8xlb6nWBoO3iWou4drQeq1wCZEp2Z416xVrU\njV6z\r\n=3XYW\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC85Tx4+N0vUIG8GQvaNJCr8e57A6mbLYuxYiAHGqj8ugIhAMpNJut+cU5Egi6HI9c94GowibOo/4/BvsPqtaLvvjT1"}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"yahgwai","email":"cpbuckland88@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.13-0_1589489728602_0.1646250490786505"},"_hasShrinkwrap":false},"0.0.13-4":{"name":"@anydotcrypto/metatransactions","version":"0.0.13-4","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build","prepublishOnly":"npm run clean && npm run build && npm run build-ts && npm run publish-contracts","preinstall":"node -e \"!process.env.npm_config_user_agent.startsWith('pnpm/') && !console.log('Install pnpm globally using \\`npm i -g pnpm\\` then do \\`pnpm i\\` to install dependencies in this repository\\n') && process.exit(1)\"","preuninstall":"node -e \"!process.env.npm_config_user_agent.startsWith('pnpm/') && !console.log('Install pnpm globally using \\`npm i -g pnpm\\` then do \\`pnpm i\\` to install dependencies in this repository\\n') && process.exit(1)\""},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single RelayHub contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nThis meta-transaction library supports both approaches. We hope it benefits the community in the following way:\n\n- **Ease of adoption:** All smart contracts can support meta-transactions without explicitly handling replay protection (e.g. [implementing a permit() standard](https://github.com/makerdao/dss/blob/master/src/dai.sol#L117-L141)).\n- **A candidate RelayHub standard:** Our minimal RelayHub.sol can be a candidate for the hard-coded RelayHub in the \\_msgSender() standard.\n- **Minimal proxy contracts:** Our ProxyAccount contracts have minimal functionality (e.g. it can only .call() to a target contract) which makes them easy to audit, reason about and adopt.\n- **Better-than-Ethereum Replay Protection:** We have implemented Nonce, MultiNonce and BitFlip, so the developer can decide if they want to ordered transactions, multiple queues of transactions, or always out-of-order transactions.\n\nThere are several libraries for constructing and signing meta-transactions, but more often than not it is mixed up with the application logic. This repository is protocol and relayer-independent such that it can become a single standard any project can adopt. Hopefully it will make it easier easier for developers to tap into third party relayer APIs and thus no longer need to re-implement the wheel of building reliable transaction infrastructure.\n\n# Table of Contents\n\n- [Getting started](#getting-started)\n- [You are now ready to authorise a meta-transaction!](#you-are-now-ready-to-authorise-a-meta-transaction-)\n  - [Example Echo Contract](#example-echo-contract)\n  - [Proxy Account Contract](#proxy-account-contract)\n  - [RelayHub](#relayhub)\n- [ProxyAccount vs RelayHub](#proxyaccount-vs-relayhub)\n  - [Proxy Account Contract](#proxy-account-contract-1)\n    - [Deploying the proxy contract](#deploying-the-proxy-contract)\n    - [Sign and encode meta-transactions](#sign-and-encode-meta-transactions)\n    - [Sign and encode meta-deployments](#sign-and-encode-meta-deployments)\n  - [Relay Hub](#relay-hub)\n    - [MsgSender.sol](#msgsendersol)\n    - [Sign and encode meta-transactions](#sign-and-encode-meta-transactions-1)\n    - [Sign and encode meta-deployments](#sign-and-encode-meta-deployments-1)\n\n# Getting started\n\nWe assume you have set up your nodejs environment and you simply need to plug-in our library.\n\n1. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. Deciding which network and replay protection to use.\n\nYou will need to import both the ChainID and Replay Protection into your code:\n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\n\nOur library currently supports MAINNET or ROPSTEN.\n\n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\n\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n\n```\n// ReplayProtection\nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\n\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. You need to decide which solution to msg.sender you want to use.\n\nFor the msg.sender solution, we cover [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub) later in the README. If you are unsure which one to use, then **_we recommend proxy account contracts as it works for all existing contracts_**.\n\n4. Time to instantiate the meta-transaction library with your prefered options!\n\nTo instantiate the proxy account forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract.\n\nImportant: It will sign meta-transactions even if the proxy account contract does not exist on the blockchain (e.g. it is not yet deployed). It is possible to send the relayer a meta-deployment (covered soon) to deploy the proxy contract and the meta-transaction. This informs the relayer to meta-deploy the proxy account contract before executing the meta-transaction. So there is no waiting/setup process.\n\nTo instantiate the RelayHub forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst relayHubForwarder = await new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.NONCE,\n    signer\n);\n```\n\nThere is a single instance of the RelayHub on each network and the forwarder links to it. All replay protection is handled by the RelayHub contract and there is no requirement to broadcast/setup in advance. Again, it only works if the target contract supports the \\_msgSender() standard.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nWe will use the Echo smart contract for both examples:\n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## Proxy Account Contract\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the signer's proxy account contract (note: it is very easy to meta-deploy the proxy account contract alongside the first meta-transaction):\n\n```\nconst isProxyDeployed = await forwarder.isContractDeployed();\nif (!isProxyDeployed) {\n    const minimalTx = await forwarder.createProxyContract();\n\n    // For our example we mimic the relayer API with a relayer wallet.\n    const proxyTx = await relayer.sendTransaction({\n      to: minimalTx.to,\n      data: minimalTx.callData,\n    });\n\n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nTo authorise a meta-transaction you must supply:\n\n- **Target** contract's address,\n- **Value** to be sent\n- **Calldata** the function name and its arguments\n\nLet's see a code sample of authorising a meta-transaction for the Echo contract:\n\n```\n// Fetch the contract and the calldata.\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: echo.address,\n    value: new BigNumber(\"0\"),\n    callData,\n});\n\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTxData,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Well done!\n\n## RelayHub\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\n\nconst forwarder = await new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWhile there is no setup/deployment to perform for the signer. It is important that your target contract supports the \\_msgSender() standard. So let's modify the Echo contract to support the standard:\n\n```\npragma solidity ^0.6.2;\nimport \"https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/account/MsgSender.sol\";\n\ncontract Echo is MsgSender {\n    event Broadcast(address signer, string message);\n\n    // In the future we will hard-code the RelayHub\n    // address into MsgSender.sol\n    constructor(address _relayHub) public {\n        relayHub = _relayHub;\n    }\n    function submit(string memory _message) public\n    {\n        address signer = _msgSender();\n        emit Broadcast(signer, _message);\n    }\n}\n```\n\nNow that the target-contract supports the \\_msgSender() standard, you must supply the following to authorise a meta-transaction:\n\n- **Target** contract's address,\n- **Calldata** the function name and its arguments\n\nUnlike proxy account contracts, the RelayHub does not yet support native transfers of ETH. Now that we have the necessary informaton let's send the meta-transaction via the RelayHub:\n\n```\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([message]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: cyberDiceCon.address,\n    callData,\n});\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst receipt = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTxData,\n});\n\nconst tx = await receipt.wait();\n```\n\nWell done!\n\n# ProxyAccount vs RelayHub\n\nAs we mentioned earlier, there are two solutions to the msg.sender problem.\n\n- **Proxy Contract Accounts**: Every user has a proxy contract with a deterministic address. All meta-transactions are sent via the user's proxy account.\n- **RelayHub**: There is no proxy account contracts. The RelayHub appends the signer's address onto the calldata that is sent to the target contract. It requires the target contract to support the \\_msgSender() standard.\n\nWhile proxy contract accounts works for all existing smart contracts, the RelayHub requires the target contract to support the \\_msgSender() standard. If supported, the RelayHub allows the signer's address to be the msg.sender in the target contract. Going forward, we hope that the RelayHub serves as a model and it can later become a precompile/a new opcode in Ethereum.\n\nNote, the RelayHub does not support holding or sending ETH. It is possible to store a balance for each signer, but we opted for a simple/minimalist RelayHub. Find out more at [this issue](https://github.com/anydotcrypto/metatransactions/issues/9) to find out why.\n\n## Proxy Account Contract\n\nThere are two contracts:\n\n- **Proxy Deployer:** Responsible for deploying all proxy account contracts.\n- **Proxy Account:** A proxy contract for a single user.\n\nThe motivation for a ProxyDeployer contract is to act as a global registry for all proxy contracts. It is only responsible for deploying proxy contract addresses and thanks to CREATE2 it ensures all signers have a deterministic proxy address.\n\nThe proxy account contract is responsible for acting as the user's identity to other smart contracts such that msg.sender is the proxy contract's address. Our forwarder library `ProxyAccountForwarder` has methods to support interacting with proxy contracts.\n\n### Deploying the proxy contract\n\nWe must check if the proxy contract is deployed before deciding to deploy it.\n\n```\nconst isDeployed: boolean = await forwarder.isContractDeployed();\nconst minimalTx: MinimalTx = await forwarder.createProxyContract();\n```\n\nThe MinimalTx has the following interface:\n\n```\ninterface MinimalTx {\n  to: string; // Target contract address\n  data: string; // Calldata for the target contract\n}\n```\n\nIt costs approximately ~110k gas (including transaction overhead) to deploy a proxy contract.\n\n### Sign and encode meta-transactions\n\nOur library supports signing the meta-transaction (and taking care of the replay protection under the hood):\n\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nIt returns forward parameters which has the following interface:\n\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address\n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Value in WEI to send\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection\n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. If desired, the forward parameters can be used to directly send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).forward(\n    params.target,\n    params.value,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it may be simpler to encode and send the meta-transaction (e.g. so it satisfies the data field of an Ethereum Transaction):\n\n```\n// Encode calldata for ProxyAccount.forward()\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: metaTxData});\n```\n\n### Sign and encode meta-deployments\n\nA very exciting feature for our library is to support meta-deployments as the proxy contract will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract\n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata:\n\n```\n  const metaDeploymentData = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: metaDeploymentData,\n  });\n```\n\nBut what about the new contract address? How do we derive it?\n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\nWell done! You have leveled up and you can now perform meta-deployments!\n\n## RelayHub\n\nThe RelayHub has a single deployed contract on the network and it is available for all users.\n\nOne way to think about the RelayHub is that it emulates the Ethereum account system. It is only responsible for keeping track of a user's replay protection and verifying their signature. If both conditions pass, then it will append the signer's address to the target contract calldata before forwarding it.\n\nAs we have mentioned several times, the RelayHub is only compatible with contracts that support the \\_msgSender() standard. But the advantage of the RelayHub is that the signer's address is the msg.sender and there is no need to deploy a user-specific contract in advance.\n\n### MsgSender.sol\n\nThe target contract must extend MsgSender.sol and include the contract address of our RelayHub. Let's have a quick look at its code:\n\n```\npragma solidity 0.6.2;\ncontract MsgSender {\n    address public relayHub;\n    function _msgSender() internal view virtual returns (address payable) {\n        if (msg.sender != relayHub) {\n            return msg.sender;\n        } else {\n            return _getRelayedCallSender();\n        }\n    }\n\n    function _getRelayedCallSender() private pure returns (address payable result) {\n        bytes memory array = msg.data;\n        uint256 index = msg.data.length;\n        assembly {\n            result := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)\n        }\n        return result;\n    }\n}\n```\n\nWhen the RelayHub forwards a call to the target contract it will append the signer's address to the msg.data. So the target contract can simply verify that msg.sender is the RelayHub contract address and then extract the signer's address from the msg.sender. It will return the signer's address to the main contract.\n\nThus the target contract must replace msg.sender with \\_msgSender():\n\n```\naddress signer = _msgSender();\n```\n\nThe original idea for msgSender originates from the gas station network (OpenGSN) and we hope to work together with them to standardise the RelayHub.sol.\n\n### Sign and encode meta-transactions\n\nOur library supports signing and encoding the meta-transaction:\n\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nThe forward parameters has the following interface:\n\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address\n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Always set to 0 for the RelayHub\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection\n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. Although it must be mentioned that `value=\"0` as the RelayHub does not support transfering ETH. If desired, the forward parameters can be used to send directly to the relayhub:\n\n```\nconst tx = await relayHubContract.connect(relayer).forward(\n    params.target,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n)\n```\n\nOf course, it may be simpler to encode and send the meta-transaction:\n\n```\n// Encode calldata for RelayHub.forward()\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: metaTxData});\n```\n\n### Sign and encode meta-deployments\n\nA very exciting feature for our library is to support meta-deployments as the RelayHubt will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract\n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the RelayHub:\n\n```\nconst tx = await relayHubContract.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata:\n\n```\n  const metaDeploymentData = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: metaDeploymentData,\n  });\n```\n\nBut what about the new contract address? How do we derive it?\n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\n^^ and that's all for now folks!\n","readmeFilename":"README.md","gitHead":"2a3a02165dfb8014c39ff2bf53bebdaf625171f1","_id":"@anydotcrypto/metatransactions@0.0.13-4","_nodeVersion":"11.14.0","_npmVersion":"6.14.5","dist":{"integrity":"sha512-PR2iofhh9UaPgsl8ISksF2vuLhen9yOkMfV9psHKkY962aS7D+oKVchyfSJ+BDbMmno/Wfe+YZmTLIi8IFIpzQ==","shasum":"885e4aea40e16eb49ddb36f1833b746f1dfaa412","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.13-4.tgz","fileCount":106,"unpackedSize":616112,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJevbcWCRA9TVsSAnZWagAAO5sP/A4VsD45CfvDq4HM9lRu\nQRcF8EWgGmojYqPkx11Dl+3RitkKh+aFvP3U8aeLAql/wcyip/cLIe0s6Czg\nqlW6BTY2/YgCCd/KzVsk4dWgLF4yJLV7dkgdc1NlPxJDSNa8v8OKjjj1ozLO\nDnpNrsyITIgt+pVgkwK7ecU+GDIXgjpgD+7sCuOZ40PG7st/+7GL8HBuaGCl\nPrMvUPh10w2bO65Hhu3eCmQcXbMpHrXD1SMM5W4APUL6yCHqatiCiHveFtxM\nu0Txx8vVN+gyVesbe7lVVXsQcwRFiP1ARbgcA8OnRDrMJdFZSjnXxWCiATv+\nciKaYKD9j3reFepeKghVGLWSAKr3dLkHqw5/lJXg5QwUNDbPdTtuJp1js9TQ\niVlD5U4lFnrGhfalY0tbo/OXKprMb/hORgo6e5sHWbINLQkrD2HLandJgCBH\nGHxj30JkHDBPIgk0c4Pz6DM3teifhe7FdcgxVa3FizSyEc3uAAv2R4P6aNn2\nqqZrCiWraCwhfO4stsIkPeRWEX7UfLvvOZSwn9RX7G9z7t3+uU48K4LSKLiz\nBm8E8LKm2/boeqVz8+Gg9P5Piv6IYQRJHHDHtAr6kuraaJ3Qx+5mk9tBBvwF\nHTq8ijIVSeGwscpPyTa7edg3MdIidcP66WpwGwIu/6cce//nxhYuVcoo2Pc/\nrtYG\r\n=60fY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIByVTOSAwHL8ytciS9JB398XLvPThBe/ipF+51yFddSHAiEAmcpKIqzKK6AfyjvRvx3nsbS6tyVAClXX0j83HZXSW/E="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"yahgwai","email":"cpbuckland88@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.13-4_1589491478163_0.12871405524955137"},"_hasShrinkwrap":false},"0.0.13-5":{"name":"@anydotcrypto/metatransactions","version":"0.0.13-5","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","execute":"ts-node src/deployment/deploy.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build","prepublishOnly":"npm run clean && npm run build && npm run build-ts && npm run publish-contracts","preinstall":"node -e \"!process.env.npm_config_user_agent.startsWith('pnpm/') && !console.log('Install pnpm globally using \\`npm i -g pnpm\\` then do \\`pnpm i\\` to install dependencies in this repository\\n') && process.exit(1)\"","preuninstall":"node -e \"!process.env.npm_config_user_agent.startsWith('pnpm/') && !console.log('Install pnpm globally using \\`npm i -g pnpm\\` then do \\`pnpm i\\` to install dependencies in this repository\\n') && process.exit(1)\""},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"gitHead":"13314e3af4867364f28a7c2da3b2b151494c4152","readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single RelayHub contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nThis meta-transaction library supports both approaches. We hope it benefits the community in the following way:\n\n- **Ease of adoption:** All smart contracts can support meta-transactions without explicitly handling replay protection (e.g. [implementing a permit() standard](https://github.com/makerdao/dss/blob/master/src/dai.sol#L117-L141)).\n- **A candidate RelayHub standard:** Our minimal RelayHub.sol can be a candidate for the hard-coded RelayHub in the \\_msgSender() standard.\n- **Minimal proxy contracts:** Our ProxyAccount contracts have minimal functionality (e.g. it can only .call() to a target contract) which makes them easy to audit, reason about and adopt.\n- **Better-than-Ethereum Replay Protection:** We have implemented Nonce, MultiNonce and BitFlip, so the developer can decide if they want to ordered transactions, multiple queues of transactions, or always out-of-order transactions.\n\nThere are several libraries for constructing and signing meta-transactions, but more often than not it is mixed up with the application logic. This repository is protocol and relayer-independent such that it can become a single standard any project can adopt. Hopefully it will make it easier easier for developers to tap into third party relayer APIs and thus no longer need to re-implement the wheel of building reliable transaction infrastructure.\n\n# Table of Contents\n\n- [Getting started](#getting-started)\n- [You are now ready to authorise a meta-transaction!](#you-are-now-ready-to-authorise-a-meta-transaction-)\n  - [Example Echo Contract](#example-echo-contract)\n  - [Proxy Account Contract](#proxy-account-contract)\n  - [RelayHub](#relayhub)\n- [ProxyAccount vs RelayHub](#proxyaccount-vs-relayhub)\n  - [Proxy Account Contract](#proxy-account-contract-1)\n    - [Deploying the proxy contract](#deploying-the-proxy-contract)\n    - [Sign and encode meta-transactions](#sign-and-encode-meta-transactions)\n    - [Sign and encode meta-deployments](#sign-and-encode-meta-deployments)\n  - [Relay Hub](#relay-hub)\n    - [MsgSender.sol](#msgsendersol)\n    - [Sign and encode meta-transactions](#sign-and-encode-meta-transactions-1)\n    - [Sign and encode meta-deployments](#sign-and-encode-meta-deployments-1)\n\n# Getting started\n\nWe assume you have set up your nodejs environment and you simply need to plug-in our library.\n\n1. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. Deciding which network and replay protection to use.\n\nYou will need to import both the ChainID and Replay Protection into your code:\n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\n\nOur library currently supports MAINNET or ROPSTEN.\n\n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\n\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n\n```\n// ReplayProtection\nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\n\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. You need to decide which solution to msg.sender you want to use.\n\nFor the msg.sender solution, we cover [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub) later in the README. If you are unsure which one to use, then **_we recommend proxy account contracts as it works for all existing contracts_**.\n\n4. Time to instantiate the meta-transaction library with your prefered options!\n\nTo instantiate the proxy account forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract.\n\nImportant: It will sign meta-transactions even if the proxy account contract does not exist on the blockchain (e.g. it is not yet deployed). It is possible to send the relayer a meta-deployment (covered soon) to deploy the proxy contract and the meta-transaction. This informs the relayer to meta-deploy the proxy account contract before executing the meta-transaction. So there is no waiting/setup process.\n\nTo instantiate the RelayHub forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst relayHubForwarder = await new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.NONCE,\n    signer\n);\n```\n\nThere is a single instance of the RelayHub on each network and the forwarder links to it. All replay protection is handled by the RelayHub contract and there is no requirement to broadcast/setup in advance. Again, it only works if the target contract supports the \\_msgSender() standard.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nWe will use the Echo smart contract for both examples:\n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## Proxy Account Contract\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the signer's proxy account contract (note: it is very easy to meta-deploy the proxy account contract alongside the first meta-transaction):\n\n```\nconst isProxyDeployed = await forwarder.isContractDeployed();\nif (!isProxyDeployed) {\n    const minimalTx = await forwarder.createProxyContract();\n\n    // For our example we mimic the relayer API with a relayer wallet.\n    const proxyTx = await relayer.sendTransaction({\n      to: minimalTx.to,\n      data: minimalTx.callData,\n    });\n\n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nTo authorise a meta-transaction you must supply:\n\n- **Target** contract's address,\n- **Value** to be sent\n- **Calldata** the function name and its arguments\n\nLet's see a code sample of authorising a meta-transaction for the Echo contract:\n\n```\n// Fetch the contract and the calldata.\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: echo.address,\n    value: new BigNumber(\"0\"),\n    callData,\n});\n\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTxData,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Well done!\n\n## RelayHub\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\n\nconst forwarder = await new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWhile there is no setup/deployment to perform for the signer. It is important that your target contract supports the \\_msgSender() standard. So let's modify the Echo contract to support the standard:\n\n```\npragma solidity ^0.6.2;\nimport \"https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/account/MsgSender.sol\";\n\ncontract Echo is MsgSender {\n    event Broadcast(address signer, string message);\n\n    // In the future we will hard-code the RelayHub\n    // address into MsgSender.sol\n    constructor(address _relayHub) public {\n        relayHub = _relayHub;\n    }\n    function submit(string memory _message) public\n    {\n        address signer = _msgSender();\n        emit Broadcast(signer, _message);\n    }\n}\n```\n\nNow that the target-contract supports the \\_msgSender() standard, you must supply the following to authorise a meta-transaction:\n\n- **Target** contract's address,\n- **Calldata** the function name and its arguments\n\nUnlike proxy account contracts, the RelayHub does not yet support native transfers of ETH. Now that we have the necessary informaton let's send the meta-transaction via the RelayHub:\n\n```\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([message]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: cyberDiceCon.address,\n    callData,\n});\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst receipt = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTxData,\n});\n\nconst tx = await receipt.wait();\n```\n\nWell done!\n\n# ProxyAccount vs RelayHub\n\nAs we mentioned earlier, there are two solutions to the msg.sender problem.\n\n- **Proxy Contract Accounts**: Every user has a proxy contract with a deterministic address. All meta-transactions are sent via the user's proxy account.\n- **RelayHub**: There is no proxy account contracts. The RelayHub appends the signer's address onto the calldata that is sent to the target contract. It requires the target contract to support the \\_msgSender() standard.\n\nWhile proxy contract accounts works for all existing smart contracts, the RelayHub requires the target contract to support the \\_msgSender() standard. If supported, the RelayHub allows the signer's address to be the msg.sender in the target contract. Going forward, we hope that the RelayHub serves as a model and it can later become a precompile/a new opcode in Ethereum.\n\nNote, the RelayHub does not support holding or sending ETH. It is possible to store a balance for each signer, but we opted for a simple/minimalist RelayHub. Find out more at [this issue](https://github.com/anydotcrypto/metatransactions/issues/9) to find out why.\n\n## Proxy Account Contract\n\nThere are two contracts:\n\n- **Proxy Deployer:** Responsible for deploying all proxy account contracts.\n- **Proxy Account:** A proxy contract for a single user.\n\nThe motivation for a ProxyDeployer contract is to act as a global registry for all proxy contracts. It is only responsible for deploying proxy contract addresses and thanks to CREATE2 it ensures all signers have a deterministic proxy address.\n\nThe proxy account contract is responsible for acting as the user's identity to other smart contracts such that msg.sender is the proxy contract's address. Our forwarder library `ProxyAccountForwarder` has methods to support interacting with proxy contracts.\n\n### Deploying the proxy contract\n\nWe must check if the proxy contract is deployed before deciding to deploy it.\n\n```\nconst isDeployed: boolean = await forwarder.isContractDeployed();\nconst minimalTx: MinimalTx = await forwarder.createProxyContract();\n```\n\nThe MinimalTx has the following interface:\n\n```\ninterface MinimalTx {\n  to: string; // Target contract address\n  data: string; // Calldata for the target contract\n}\n```\n\nIt costs approximately ~110k gas (including transaction overhead) to deploy a proxy contract.\n\n### Sign and encode meta-transactions\n\nOur library supports signing the meta-transaction (and taking care of the replay protection under the hood):\n\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nIt returns forward parameters which has the following interface:\n\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address\n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Value in WEI to send\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection\n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. If desired, the forward parameters can be used to directly send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).forward(\n    params.target,\n    params.value,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it may be simpler to encode and send the meta-transaction (e.g. so it satisfies the data field of an Ethereum Transaction):\n\n```\n// Encode calldata for ProxyAccount.forward()\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: metaTxData});\n```\n\n### Sign and encode meta-deployments\n\nA very exciting feature for our library is to support meta-deployments as the proxy contract will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract\n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata:\n\n```\n  const metaDeploymentData = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: metaDeploymentData,\n  });\n```\n\nBut what about the new contract address? How do we derive it?\n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\nWell done! You have leveled up and you can now perform meta-deployments!\n\n## RelayHub\n\nThe RelayHub has a single deployed contract on the network and it is available for all users.\n\nOne way to think about the RelayHub is that it emulates the Ethereum account system. It is only responsible for keeping track of a user's replay protection and verifying their signature. If both conditions pass, then it will append the signer's address to the target contract calldata before forwarding it.\n\nAs we have mentioned several times, the RelayHub is only compatible with contracts that support the \\_msgSender() standard. But the advantage of the RelayHub is that the signer's address is the msg.sender and there is no need to deploy a user-specific contract in advance.\n\n### MsgSender.sol\n\nThe target contract must extend MsgSender.sol and include the contract address of our RelayHub. Let's have a quick look at its code:\n\n```\npragma solidity 0.6.2;\ncontract MsgSender {\n    address public relayHub;\n    function _msgSender() internal view virtual returns (address payable) {\n        if (msg.sender != relayHub) {\n            return msg.sender;\n        } else {\n            return _getRelayedCallSender();\n        }\n    }\n\n    function _getRelayedCallSender() private pure returns (address payable result) {\n        bytes memory array = msg.data;\n        uint256 index = msg.data.length;\n        assembly {\n            result := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)\n        }\n        return result;\n    }\n}\n```\n\nWhen the RelayHub forwards a call to the target contract it will append the signer's address to the msg.data. So the target contract can simply verify that msg.sender is the RelayHub contract address and then extract the signer's address from the msg.sender. It will return the signer's address to the main contract.\n\nThus the target contract must replace msg.sender with \\_msgSender():\n\n```\naddress signer = _msgSender();\n```\n\nThe original idea for msgSender originates from the gas station network (OpenGSN) and we hope to work together with them to standardise the RelayHub.sol.\n\n### Sign and encode meta-transactions\n\nOur library supports signing and encoding the meta-transaction:\n\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nThe forward parameters has the following interface:\n\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address\n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Always set to 0 for the RelayHub\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection\n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. Although it must be mentioned that `value=\"0` as the RelayHub does not support transfering ETH. If desired, the forward parameters can be used to send directly to the relayhub:\n\n```\nconst tx = await relayHubContract.connect(relayer).forward(\n    params.target,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n)\n```\n\nOf course, it may be simpler to encode and send the meta-transaction:\n\n```\n// Encode calldata for RelayHub.forward()\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: metaTxData});\n```\n\n### Sign and encode meta-deployments\n\nA very exciting feature for our library is to support meta-deployments as the RelayHubt will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract\n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the RelayHub:\n\n```\nconst tx = await relayHubContract.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata:\n\n```\n  const metaDeploymentData = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: metaDeploymentData,\n  });\n```\n\nBut what about the new contract address? How do we derive it?\n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\n^^ and that's all for now folks!\n","readmeFilename":"README.md","_id":"@anydotcrypto/metatransactions@0.0.13-5","_nodeVersion":"11.10.1","_npmVersion":"6.14.5","dist":{"integrity":"sha512-D7/33N4cJHzSKwQkHYCrxWsSshnnnUI/H1DsEokFNnLvVWwn5GG7LNY8XV5+m/+S49LuH6t+FnWVz8Zfbc+Enw==","shasum":"f33afad3217ee174c9a942a305005a689b46ed99","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.13-5.tgz","fileCount":110,"unpackedSize":621075,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJevtbPCRA9TVsSAnZWagAAXhcP/2ffy8j/j8KPpOpz6+77\ngsXIIxqRlk61KWa489dGjT/RM8LMtlxN1gInv3em9lp5DKnhU0pK1B4XiVlD\nRLQlLvp4yGPGRz/7zc7qJt8ZeTdz/jSuStjAidQv2sdp/Gx8i1O/yWbt1dLA\n2Nla7zvYyxdiLP2vGK/1s2Soc66QuqjLH4mKOusvn4tUE635DtqsD7OhQsjV\nYfAORfbhHWYzmXBjd2DRPxNQi23K0uq1swmmuLJ3fx0tRNtooJBlMWmKe4+z\nZEerRvwHba0NirLDO5NJiTt5UxMOHrP8lN7ZjJQsjkJkNsPMZGHLiP5ZHhvG\nyFjU43RtcDPIzehZ6okp0yubGVB1AQXAd1S7zGQcHa4pMqq0oXlJH+1OxZJ5\n0cUoBqH+1nSa0FcbECEVr9326i0YlCDRuwbx8BcIDxu9X6etzCbAsll37j3J\nXoiPhiEWL4dwiBpM4uOyXNfN1STEGKuRgolaNDRMdlvi31D+Yn1sLoGVrgvA\nFl713tgAw6OOLHlxyBiCCvGKPAFHzjWMjIo9BSy2+Fk/koCQzRH+nP0oTGx+\n6gjxXZm+U5y4Rm5kdcKS9b9eA+Y0NnGm2SN3xvmruolGNHOSlwQa2jYNYVyP\npRqLpb/AxYN5a0le16Fyr40Xf09KjFmmUoga6Iovd/lm0RJdWkF5Kpuhkkw+\nV8UQ\r\n=Bx0m\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIClTVEgFbRMicrFXYkkDOoEAgIFs12cKaXNfOO+lNjb+AiEAgfr1+oi4aER5rDoxvVxE/nT9d+Jnvhp7TiijlRJs8A0="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.13-5_1589565135077_0.06357239746698085"},"_hasShrinkwrap":false},"0.0.13-6":{"name":"@anydotcrypto/metatransactions","version":"0.0.13-6","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deploy.ts","generateSeed":"ts-node example/generateSeed.ts","echo-example":"ts-node example/proxyaccounts/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build","preinstall":"node -e \"!process.env.npm_config_user_agent.startsWith('pnpm/') && !console.log('Install pnpm globally using \\`npm i -g pnpm\\` then do \\`pnpm i\\` to install dependencies in this repository\\n') && process.exit(1)\"","preuninstall":"node -e \"!process.env.npm_config_user_agent.startsWith('pnpm/') && !console.log('Install pnpm globally using \\`npm i -g pnpm\\` then do \\`pnpm i\\` to install dependencies in this repository\\n') && process.exit(1)\""},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single RelayHub contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nThis meta-transaction library supports both approaches. We hope it benefits the community in the following way:\n\n- **Ease of adoption:** All smart contracts can support meta-transactions without explicitly handling replay protection (e.g. [implementing a permit() standard](https://github.com/makerdao/dss/blob/master/src/dai.sol#L117-L141)).\n- **A candidate RelayHub standard:** Our minimal RelayHub.sol can be a candidate for the hard-coded RelayHub in the \\_msgSender() standard.\n- **Minimal proxy contracts:** Our ProxyAccount contracts have minimal functionality (e.g. it can only .call() to a target contract) which makes them easy to audit, reason about and adopt.\n- **Better-than-Ethereum Replay Protection:** We have implemented Nonce, MultiNonce and BitFlip, so the developer can decide if they want to ordered transactions, multiple queues of transactions, or always out-of-order transactions.\n\nThere are several libraries for constructing and signing meta-transactions, but more often than not it is mixed up with the application logic. This repository is protocol and relayer-independent such that it can become a single standard any project can adopt. Hopefully it will make it easier easier for developers to tap into third party relayer APIs and thus no longer need to re-implement the wheel of building reliable transaction infrastructure.\n\n# Table of Contents\n\n- [Getting started](#getting-started)\n- [You are now ready to authorise a meta-transaction!](#you-are-now-ready-to-authorise-a-meta-transaction-)\n  - [Example Echo Contract](#example-echo-contract)\n  - [Proxy Account Contract](#proxy-account-contract)\n  - [RelayHub](#relayhub)\n- [ProxyAccount vs RelayHub](#proxyaccount-vs-relayhub)\n  - [Proxy Account Contract](#proxy-account-contract-1)\n    - [Deploying the proxy contract](#deploying-the-proxy-contract)\n    - [Sign and encode meta-transactions](#sign-and-encode-meta-transactions)\n    - [Sign and encode meta-deployments](#sign-and-encode-meta-deployments)\n  - [Relay Hub](#relay-hub)\n    - [MsgSender.sol](#msgsendersol)\n    - [Sign and encode meta-transactions](#sign-and-encode-meta-transactions-1)\n    - [Sign and encode meta-deployments](#sign-and-encode-meta-deployments-1)\n\n# Getting started\n\nWe assume you have set up your nodejs environment and you simply need to plug-in our library.\n\n1. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. Deciding which network and replay protection to use.\n\nYou will need to import both the ChainID and Replay Protection into your code:\n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\n\nOur library currently supports MAINNET or ROPSTEN.\n\n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\n\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n\n```\n// ReplayProtection\nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\n\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. You need to decide which solution to msg.sender you want to use.\n\nFor the msg.sender solution, we cover [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub) later in the README. If you are unsure which one to use, then **_we recommend proxy account contracts as it works for all existing contracts_**.\n\n4. Time to instantiate the meta-transaction library with your prefered options!\n\nTo instantiate the proxy account forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract.\n\nImportant: It will sign meta-transactions even if the proxy account contract does not exist on the blockchain (e.g. it is not yet deployed). It is possible to send the relayer a meta-deployment (covered soon) to deploy the proxy contract and the meta-transaction. This informs the relayer to meta-deploy the proxy account contract before executing the meta-transaction. So there is no waiting/setup process.\n\nTo instantiate the RelayHub forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst relayHubForwarder = await new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.NONCE,\n    signer\n);\n```\n\nThere is a single instance of the RelayHub on each network and the forwarder links to it. All replay protection is handled by the RelayHub contract and there is no requirement to broadcast/setup in advance. Again, it only works if the target contract supports the \\_msgSender() standard.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nWe will use the Echo smart contract for both examples:\n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## Proxy Account Contract\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the signer's proxy account contract (note: it is very easy to meta-deploy the proxy account contract alongside the first meta-transaction):\n\n```\nconst isProxyDeployed = await forwarder.isContractDeployed();\nif (!isProxyDeployed) {\n    const minimalTx = await forwarder.createProxyContract();\n\n    // For our example we mimic the relayer API with a relayer wallet.\n    const proxyTx = await relayer.sendTransaction({\n      to: minimalTx.to,\n      data: minimalTx.callData,\n    });\n\n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nTo authorise a meta-transaction you must supply:\n\n- **Target** contract's address,\n- **Value** to be sent\n- **Calldata** the function name and its arguments\n\nLet's see a code sample of authorising a meta-transaction for the Echo contract:\n\n```\n// Fetch the contract and the calldata.\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: echo.address,\n    value: new BigNumber(\"0\"),\n    callData,\n});\n\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTxData,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Well done!\n\n## RelayHub\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\n\nconst forwarder = await new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWhile there is no setup/deployment to perform for the signer. It is important that your target contract supports the \\_msgSender() standard. So let's modify the Echo contract to support the standard:\n\n```\npragma solidity ^0.6.2;\nimport \"https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/account/MsgSender.sol\";\n\ncontract Echo is MsgSender {\n    event Broadcast(address signer, string message);\n\n    // In the future we will hard-code the RelayHub\n    // address into MsgSender.sol\n    constructor(address _relayHub) public {\n        relayHub = _relayHub;\n    }\n    function submit(string memory _message) public\n    {\n        address signer = _msgSender();\n        emit Broadcast(signer, _message);\n    }\n}\n```\n\nNow that the target-contract supports the \\_msgSender() standard, you must supply the following to authorise a meta-transaction:\n\n- **Target** contract's address,\n- **Calldata** the function name and its arguments\n\nUnlike proxy account contracts, the RelayHub does not yet support native transfers of ETH. Now that we have the necessary informaton let's send the meta-transaction via the RelayHub:\n\n```\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([message]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: cyberDiceCon.address,\n    callData,\n});\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst receipt = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTxData,\n});\n\nconst tx = await receipt.wait();\n```\n\nWell done!\n\n# ProxyAccount vs RelayHub\n\nAs we mentioned earlier, there are two solutions to the msg.sender problem.\n\n- **Proxy Contract Accounts**: Every user has a proxy contract with a deterministic address. All meta-transactions are sent via the user's proxy account.\n- **RelayHub**: There is no proxy account contracts. The RelayHub appends the signer's address onto the calldata that is sent to the target contract. It requires the target contract to support the \\_msgSender() standard.\n\nWhile proxy contract accounts works for all existing smart contracts, the RelayHub requires the target contract to support the \\_msgSender() standard. If supported, the RelayHub allows the signer's address to be the msg.sender in the target contract. Going forward, we hope that the RelayHub serves as a model and it can later become a precompile/a new opcode in Ethereum.\n\nNote, the RelayHub does not support holding or sending ETH. It is possible to store a balance for each signer, but we opted for a simple/minimalist RelayHub. Find out more at [this issue](https://github.com/anydotcrypto/metatransactions/issues/9) to find out why.\n\n## Proxy Account Contract\n\nThere are two contracts:\n\n- **Proxy Deployer:** Responsible for deploying all proxy account contracts.\n- **Proxy Account:** A proxy contract for a single user.\n\nThe motivation for a ProxyDeployer contract is to act as a global registry for all proxy contracts. It is only responsible for deploying proxy contract addresses and thanks to CREATE2 it ensures all signers have a deterministic proxy address.\n\nThe proxy account contract is responsible for acting as the user's identity to other smart contracts such that msg.sender is the proxy contract's address. Our forwarder library `ProxyAccountForwarder` has methods to support interacting with proxy contracts.\n\n### Deploying the proxy contract\n\nWe must check if the proxy contract is deployed before deciding to deploy it.\n\n```\nconst isDeployed: boolean = await forwarder.isContractDeployed();\nconst minimalTx: MinimalTx = await forwarder.createProxyContract();\n```\n\nThe MinimalTx has the following interface:\n\n```\ninterface MinimalTx {\n  to: string; // Target contract address\n  data: string; // Calldata for the target contract\n}\n```\n\nIt costs approximately ~110k gas (including transaction overhead) to deploy a proxy contract.\n\n### Sign and encode meta-transactions\n\nOur library supports signing the meta-transaction (and taking care of the replay protection under the hood):\n\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nIt returns forward parameters which has the following interface:\n\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address\n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Value in WEI to send\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection\n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. If desired, the forward parameters can be used to directly send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).forward(\n    params.target,\n    params.value,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it may be simpler to encode and send the meta-transaction (e.g. so it satisfies the data field of an Ethereum Transaction):\n\n```\n// Encode calldata for ProxyAccount.forward()\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: metaTxData});\n```\n\n### Sign and encode meta-deployments\n\nA very exciting feature for our library is to support meta-deployments as the proxy contract will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract\n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata:\n\n```\n  const metaDeploymentData = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: metaDeploymentData,\n  });\n```\n\nBut what about the new contract address? How do we derive it?\n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\nWell done! You have leveled up and you can now perform meta-deployments!\n\n## RelayHub\n\nThe RelayHub has a single deployed contract on the network and it is available for all users.\n\nOne way to think about the RelayHub is that it emulates the Ethereum account system. It is only responsible for keeping track of a user's replay protection and verifying their signature. If both conditions pass, then it will append the signer's address to the target contract calldata before forwarding it.\n\nAs we have mentioned several times, the RelayHub is only compatible with contracts that support the \\_msgSender() standard. But the advantage of the RelayHub is that the signer's address is the msg.sender and there is no need to deploy a user-specific contract in advance.\n\n### MsgSender.sol\n\nThe target contract must extend MsgSender.sol and include the contract address of our RelayHub. Let's have a quick look at its code:\n\n```\npragma solidity 0.6.2;\ncontract MsgSender {\n    address public relayHub;\n    function _msgSender() internal view virtual returns (address payable) {\n        if (msg.sender != relayHub) {\n            return msg.sender;\n        } else {\n            return _getRelayedCallSender();\n        }\n    }\n\n    function _getRelayedCallSender() private pure returns (address payable result) {\n        bytes memory array = msg.data;\n        uint256 index = msg.data.length;\n        assembly {\n            result := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)\n        }\n        return result;\n    }\n}\n```\n\nWhen the RelayHub forwards a call to the target contract it will append the signer's address to the msg.data. So the target contract can simply verify that msg.sender is the RelayHub contract address and then extract the signer's address from the msg.sender. It will return the signer's address to the main contract.\n\nThus the target contract must replace msg.sender with \\_msgSender():\n\n```\naddress signer = _msgSender();\n```\n\nThe original idea for msgSender originates from the gas station network (OpenGSN) and we hope to work together with them to standardise the RelayHub.sol.\n\n### Sign and encode meta-transactions\n\nOur library supports signing and encoding the meta-transaction:\n\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nThe forward parameters has the following interface:\n\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address\n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Always set to 0 for the RelayHub\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection\n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. Although it must be mentioned that `value=\"0` as the RelayHub does not support transfering ETH. If desired, the forward parameters can be used to send directly to the relayhub:\n\n```\nconst tx = await relayHubContract.connect(relayer).forward(\n    params.target,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n)\n```\n\nOf course, it may be simpler to encode and send the meta-transaction:\n\n```\n// Encode calldata for RelayHub.forward()\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: metaTxData});\n```\n\n### Sign and encode meta-deployments\n\nA very exciting feature for our library is to support meta-deployments as the RelayHubt will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract\n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the RelayHub:\n\n```\nconst tx = await relayHubContract.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata:\n\n```\n  const metaDeploymentData = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: metaDeploymentData,\n  });\n```\n\nBut what about the new contract address? How do we derive it?\n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\n^^ and that's all for now folks!\n","readmeFilename":"README.md","gitHead":"515c35768c5edc6417e3251029c7284bb11af627","_id":"@anydotcrypto/metatransactions@0.0.13-6","_nodeVersion":"11.14.0","_npmVersion":"6.14.5","dist":{"integrity":"sha512-FbeeA9CefKwd573e3QhFB7M2Bemr8x7MspLOJsN1yZAk374+sFNRydfSPv7ur0v5+5uAr05Uhy1/0I5wZpqPLg==","shasum":"39bcc175c18d6074a16e74d34e9dc86acbbc9ed1","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.13-6.tgz","fileCount":121,"unpackedSize":655820,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJev9+rCRA9TVsSAnZWagAA++8P/0NQLHpPbFEblbRUKoEr\nsPgNfXn1GEshx/Ws8h7W7LzfA6fY957sboQzGEOPRa/rTBNNzIkU14AVf3kD\nj53dTbvVp5BF8wMU85AWG0RR8sTTLwe9tg8QZOQ2/4iJQkn3/Kc3sY20jpOo\nBXOKQhqfwynFVLsnPXT9AW/hcEDmLpXY5KqzDKqc5dnNe6h9hUor9r5M6OqT\nEetbKuPlvBw9r1GGTYVERwa42MUC7ltApf56bEybW8TKHxTw307nIF56Mt+h\ngIQ4jzlXRdVTi6qfeH6iP7oCbZ7gwlJQ3gtxh7fnifMRIctNp/WLQMT/ec9Q\np2zKMGFGRRfMkoSyGpf8IzAk8oI1olZXAlqI6KysOE8ov61+Nb7xddjRtkqE\n2UEU2nFJ4oOLOzv8P56YCwQTqEeI9wqKIMxJDYCf/Rrq3zB4j9VkPfWi6mAB\n4jNqsfZJA4fkKgZw/pb6fgxESdTy/9yg3wski1PkZBtRyXd7n+d+C2sOQgSA\nR1KqHmDqWW18/mt4J8Y78fPoKaYUGuSf7n3qFfz93kEkjOcys3LkKnf9tnz/\nn675B+j3yCxmVVIKwwJaTA81X0yiTqNwuBdz4JKZCMr+hzL0e/kXN+dPaFXm\nM2KRaw5ay8G4Ttso+uI+L1Yrlg8b1ITellPCuBtvOZ8rPbVZymjBAMK35gS8\nrfnk\r\n=NjwQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICdcEAB54IOKVhSFs8gJ5UmcPhAD6ns3TdFCR6lvnembAiEAvSQ6nrDrFEdaVjhbr0cPvbWFPKxk14nxZao2IKq7VCQ="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"yahgwai","email":"cpbuckland88@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.13-6_1589632938945_0.6102203183773025"},"_hasShrinkwrap":false},"0.0.13-7":{"name":"@anydotcrypto/metatransactions","version":"0.0.13-7","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deploy.ts","generateSeed":"ts-node example/generateSeed.ts","echo-example":"ts-node example/proxyaccounts/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build","preinstall":"node -e \"!process.env.npm_config_user_agent.startsWith('pnpm/') && !console.log('Install pnpm globally using \\`npm i -g pnpm\\` then do \\`pnpm i\\` to install dependencies in this repository\\n') && process.exit(1)\"","preuninstall":"node -e \"!process.env.npm_config_user_agent.startsWith('pnpm/') && !console.log('Install pnpm globally using \\`npm i -g pnpm\\` then do \\`pnpm i\\` to install dependencies in this repository\\n') && process.exit(1)\""},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"gitHead":"742760332a51f4392c004cb2c04081c4cbde0db3","readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single RelayHub contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nThis meta-transaction library supports both approaches. We hope it benefits the community in the following way:\n\n- **Ease of adoption:** All smart contracts can support meta-transactions without explicitly handling replay protection (e.g. [implementing a permit() standard](https://github.com/makerdao/dss/blob/master/src/dai.sol#L117-L141)).\n- **A candidate RelayHub standard:** Our minimal RelayHub.sol can be a candidate for the hard-coded RelayHub in the \\_msgSender() standard.\n- **Minimal proxy contracts:** Our ProxyAccount contracts have minimal functionality (e.g. it can only .call() to a target contract) which makes them easy to audit, reason about and adopt.\n- **Better-than-Ethereum Replay Protection:** We have implemented Nonce, MultiNonce and BitFlip, so the developer can decide if they want to ordered transactions, multiple queues of transactions, or always out-of-order transactions.\n\nThere are several libraries for constructing and signing meta-transactions, but more often than not it is mixed up with the application logic. This repository is protocol and relayer-independent such that it can become a single standard any project can adopt. Hopefully it will make it easier easier for developers to tap into third party relayer APIs and thus no longer need to re-implement the wheel of building reliable transaction infrastructure.\n\n# Table of Contents\n\n- [Getting started](#getting-started)\n- [You are now ready to authorise a meta-transaction!](#you-are-now-ready-to-authorise-a-meta-transaction-)\n  - [Example Echo Contract](#example-echo-contract)\n  - [Proxy Account Contract](#proxy-account-contract)\n  - [RelayHub](#relayhub)\n- [ProxyAccount vs RelayHub](#proxyaccount-vs-relayhub)\n  - [Proxy Account Contract](#proxy-account-contract-1)\n    - [Deploying the proxy contract](#deploying-the-proxy-contract)\n    - [Sign and encode meta-transactions](#sign-and-encode-meta-transactions)\n    - [Sign and encode meta-deployments](#sign-and-encode-meta-deployments)\n  - [Relay Hub](#relay-hub)\n    - [MsgSender.sol](#msgsendersol)\n    - [Sign and encode meta-transactions](#sign-and-encode-meta-transactions-1)\n    - [Sign and encode meta-deployments](#sign-and-encode-meta-deployments-1)\n\n# Getting started\n\nWe assume you have set up your nodejs environment and you simply need to plug-in our library.\n\n1. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. Deciding which network and replay protection to use.\n\nYou will need to import both the ChainID and Replay Protection into your code:\n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\n\nOur library currently supports MAINNET or ROPSTEN.\n\n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\n\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n\n```\n// ReplayProtection\nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\n\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. You need to decide which solution to msg.sender you want to use.\n\nFor the msg.sender solution, we cover [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub) later in the README. If you are unsure which one to use, then **_we recommend proxy account contracts as it works for all existing contracts_**.\n\n4. Time to instantiate the meta-transaction library with your prefered options!\n\nTo instantiate the proxy account forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract.\n\nImportant: It will sign meta-transactions even if the proxy account contract does not exist on the blockchain (e.g. it is not yet deployed). It is possible to send the relayer a meta-deployment (covered soon) to deploy the proxy contract and the meta-transaction. This informs the relayer to meta-deploy the proxy account contract before executing the meta-transaction. So there is no waiting/setup process.\n\nTo instantiate the RelayHub forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst relayHubForwarder = await new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.NONCE,\n    signer\n);\n```\n\nThere is a single instance of the RelayHub on each network and the forwarder links to it. All replay protection is handled by the RelayHub contract and there is no requirement to broadcast/setup in advance. Again, it only works if the target contract supports the \\_msgSender() standard.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nWe will use the Echo smart contract for both examples:\n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## Proxy Account Contract\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the signer's proxy account contract (note: it is very easy to meta-deploy the proxy account contract alongside the first meta-transaction):\n\n```\nconst isProxyDeployed = await forwarder.isContractDeployed();\nif (!isProxyDeployed) {\n    const minimalTx = await forwarder.createProxyContract();\n\n    // For our example we mimic the relayer API with a relayer wallet.\n    const proxyTx = await relayer.sendTransaction({\n      to: minimalTx.to,\n      data: minimalTx.callData,\n    });\n\n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nTo authorise a meta-transaction you must supply:\n\n- **Target** contract's address,\n- **Value** to be sent\n- **Calldata** the function name and its arguments\n\nLet's see a code sample of authorising a meta-transaction for the Echo contract:\n\n```\n// Fetch the contract and the calldata.\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: echo.address,\n    value: new BigNumber(\"0\"),\n    callData,\n});\n\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTxData,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Well done!\n\n## RelayHub\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\n\nconst forwarder = await new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWhile there is no setup/deployment to perform for the signer. It is important that your target contract supports the \\_msgSender() standard. So let's modify the Echo contract to support the standard:\n\n```\npragma solidity ^0.6.2;\nimport \"https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/account/MsgSender.sol\";\n\ncontract Echo is MsgSender {\n    event Broadcast(address signer, string message);\n\n    // In the future we will hard-code the RelayHub\n    // address into MsgSender.sol\n    constructor(address _relayHub) public {\n        relayHub = _relayHub;\n    }\n    function submit(string memory _message) public\n    {\n        address signer = _msgSender();\n        emit Broadcast(signer, _message);\n    }\n}\n```\n\nNow that the target-contract supports the \\_msgSender() standard, you must supply the following to authorise a meta-transaction:\n\n- **Target** contract's address,\n- **Calldata** the function name and its arguments\n\nUnlike proxy account contracts, the RelayHub does not yet support native transfers of ETH. Now that we have the necessary informaton let's send the meta-transaction via the RelayHub:\n\n```\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([message]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: cyberDiceCon.address,\n    callData,\n});\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst receipt = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTxData,\n});\n\nconst tx = await receipt.wait();\n```\n\nWell done!\n\n# ProxyAccount vs RelayHub\n\nAs we mentioned earlier, there are two solutions to the msg.sender problem.\n\n- **Proxy Contract Accounts**: Every user has a proxy contract with a deterministic address. All meta-transactions are sent via the user's proxy account.\n- **RelayHub**: There is no proxy account contracts. The RelayHub appends the signer's address onto the calldata that is sent to the target contract. It requires the target contract to support the \\_msgSender() standard.\n\nWhile proxy contract accounts works for all existing smart contracts, the RelayHub requires the target contract to support the \\_msgSender() standard. If supported, the RelayHub allows the signer's address to be the msg.sender in the target contract. Going forward, we hope that the RelayHub serves as a model and it can later become a precompile/a new opcode in Ethereum.\n\nNote, the RelayHub does not support holding or sending ETH. It is possible to store a balance for each signer, but we opted for a simple/minimalist RelayHub. Find out more at [this issue](https://github.com/anydotcrypto/metatransactions/issues/9) to find out why.\n\n## Proxy Account Contract\n\nThere are two contracts:\n\n- **Proxy Deployer:** Responsible for deploying all proxy account contracts.\n- **Proxy Account:** A proxy contract for a single user.\n\nThe motivation for a ProxyDeployer contract is to act as a global registry for all proxy contracts. It is only responsible for deploying proxy contract addresses and thanks to CREATE2 it ensures all signers have a deterministic proxy address.\n\nThe proxy account contract is responsible for acting as the user's identity to other smart contracts such that msg.sender is the proxy contract's address. Our forwarder library `ProxyAccountForwarder` has methods to support interacting with proxy contracts.\n\n### Deploying the proxy contract\n\nWe must check if the proxy contract is deployed before deciding to deploy it.\n\n```\nconst isDeployed: boolean = await forwarder.isContractDeployed();\nconst minimalTx: MinimalTx = await forwarder.createProxyContract();\n```\n\nThe MinimalTx has the following interface:\n\n```\ninterface MinimalTx {\n  to: string; // Target contract address\n  data: string; // Calldata for the target contract\n}\n```\n\nIt costs approximately ~110k gas (including transaction overhead) to deploy a proxy contract.\n\n### Sign and encode meta-transactions\n\nOur library supports signing the meta-transaction (and taking care of the replay protection under the hood):\n\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nIt returns forward parameters which has the following interface:\n\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address\n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Value in WEI to send\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection\n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. If desired, the forward parameters can be used to directly send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).forward(\n    params.target,\n    params.value,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it may be simpler to encode and send the meta-transaction (e.g. so it satisfies the data field of an Ethereum Transaction):\n\n```\n// Encode calldata for ProxyAccount.forward()\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: metaTxData});\n```\n\n### Sign and encode meta-deployments\n\nA very exciting feature for our library is to support meta-deployments as the proxy contract will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract\n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata:\n\n```\n  const metaDeploymentData = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: metaDeploymentData,\n  });\n```\n\nBut what about the new contract address? How do we derive it?\n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\nWell done! You have leveled up and you can now perform meta-deployments!\n\n## RelayHub\n\nThe RelayHub has a single deployed contract on the network and it is available for all users.\n\nOne way to think about the RelayHub is that it emulates the Ethereum account system. It is only responsible for keeping track of a user's replay protection and verifying their signature. If both conditions pass, then it will append the signer's address to the target contract calldata before forwarding it.\n\nAs we have mentioned several times, the RelayHub is only compatible with contracts that support the \\_msgSender() standard. But the advantage of the RelayHub is that the signer's address is the msg.sender and there is no need to deploy a user-specific contract in advance.\n\n### MsgSender.sol\n\nThe target contract must extend MsgSender.sol and include the contract address of our RelayHub. Let's have a quick look at its code:\n\n```\npragma solidity 0.6.2;\ncontract MsgSender {\n    address public relayHub;\n    function _msgSender() internal view virtual returns (address payable) {\n        if (msg.sender != relayHub) {\n            return msg.sender;\n        } else {\n            return _getRelayedCallSender();\n        }\n    }\n\n    function _getRelayedCallSender() private pure returns (address payable result) {\n        bytes memory array = msg.data;\n        uint256 index = msg.data.length;\n        assembly {\n            result := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)\n        }\n        return result;\n    }\n}\n```\n\nWhen the RelayHub forwards a call to the target contract it will append the signer's address to the msg.data. So the target contract can simply verify that msg.sender is the RelayHub contract address and then extract the signer's address from the msg.sender. It will return the signer's address to the main contract.\n\nThus the target contract must replace msg.sender with \\_msgSender():\n\n```\naddress signer = _msgSender();\n```\n\nThe original idea for msgSender originates from the gas station network (OpenGSN) and we hope to work together with them to standardise the RelayHub.sol.\n\n### Sign and encode meta-transactions\n\nOur library supports signing and encoding the meta-transaction:\n\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nThe forward parameters has the following interface:\n\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address\n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Always set to 0 for the RelayHub\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection\n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. Although it must be mentioned that `value=\"0` as the RelayHub does not support transfering ETH. If desired, the forward parameters can be used to send directly to the relayhub:\n\n```\nconst tx = await relayHubContract.connect(relayer).forward(\n    params.target,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n)\n```\n\nOf course, it may be simpler to encode and send the meta-transaction:\n\n```\n// Encode calldata for RelayHub.forward()\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: metaTxData});\n```\n\n### Sign and encode meta-deployments\n\nA very exciting feature for our library is to support meta-deployments as the RelayHubt will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract\n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the RelayHub:\n\n```\nconst tx = await relayHubContract.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata:\n\n```\n  const metaDeploymentData = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: metaDeploymentData,\n  });\n```\n\nBut what about the new contract address? How do we derive it?\n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\n^^ and that's all for now folks!\n","readmeFilename":"README.md","_id":"@anydotcrypto/metatransactions@0.0.13-7","_nodeVersion":"11.14.0","_npmVersion":"6.14.5","dist":{"integrity":"sha512-Uh2P4wuyhltUmTlT6jhIg/w3EleKai5LwutxrSDIXLgmIK6OdfBqJIYcZUjBhrOY+79GcRWxg0a1NL0AERw9LQ==","shasum":"e2ae69f5db458230ef80c88dfca6fcd40e1a3ac3","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.13-7.tgz","fileCount":121,"unpackedSize":655820,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJev+FJCRA9TVsSAnZWagAAi0wP/3fSEv3gkbAQp3Ihsqk3\npeGbTPu0oq7oesEZ9pqnFfkzBi9xmEsUcKf312EisgzUFn+EyErhh6l+NjhS\neGEtpze3XqawJNEwqHLuSOMCNEndTgOeTxDhdX4wdUOxHjbxEwSr3nCmk8OE\nWhehySaWkGMdOXSO1Ow3A7IK2zpkA/dn3kIOzFduy+zhCAiBiCXOH4PTXkC+\nA98Im4xwUYNr/zS66rJ6E6oh5F4VcSoMbwNG4MzSngqEjxoi3T5JTEJXB23X\nBjMPBhYc06SA+FUNJ+9wnZnuGqMb+NvbGigUsW70QCEj7JO3p04hwea19hgn\n9KoKAkKJFh5Qu9b0qAiEIdI++fvU/Ak2w30OphTXOXtZCGLb+YGGw1XkhJlE\nkE+YZMj179qL0Su5h5nKud2WHoZEwqxxbeC24VzsF8+PfDtjEYYmlsm2Pqv8\n2rwq/Pj1sPYdjGbDr2YDAx7ERcK6UkopWdNycMoL/EB8RMtQCSxz0hSLDtAH\ngd/XrH9r3p47t/n8qEDBG1hhlZJNkGjKTJzSEgCVYGsOYmj/7O8yNPjeW+qZ\nmCVYOru6W+rB5MCZmZuz2a8BElZ66V+xsZLAkPkS4hlpYTk9bXpg/+KkVp+K\nm7K0tnxFac3ScKADkc+pvzpinnD5sAwCrXnvsAJWfKuq96a3sXuaWcoxFoL4\nBWDI\r\n=VFYk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAbRGVopFqWw4aY365NVzKs/gXgsEMZ/K5GFSUtF3Vn/AiEAzZVoW3yQ2K4fT/9UOQFyCUtuZ5CbB3H0DZwP+afy7pc="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"yahgwai","email":"cpbuckland88@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.13-7_1589633353341_0.6608317921036868"},"_hasShrinkwrap":false},"0.0.13-8":{"name":"@anydotcrypto/metatransactions","version":"0.0.13-8","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deploy.ts","generateSeed":"ts-node example/generateSeed.ts","echo-example":"ts-node example/proxyaccounts/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build","preinstall":"node -e \"!process.env.npm_config_user_agent.startsWith('pnpm/') && !console.log('Install pnpm globally using \\`npm i -g pnpm\\` then do \\`pnpm i\\` to install dependencies in this repository\\n') && process.exit(1)\"","preuninstall":"node -e \"!process.env.npm_config_user_agent.startsWith('pnpm/') && !console.log('Install pnpm globally using \\`npm i -g pnpm\\` then do \\`pnpm i\\` to install dependencies in this repository\\n') && process.exit(1)\""},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"gitHead":"337e2c1f6653a6dbe2a9e941c58558ea2da9a688","readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single RelayHub contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nThis meta-transaction library supports both approaches. We hope it benefits the community in the following way:\n\n- **Ease of adoption:** All smart contracts can support meta-transactions without explicitly handling replay protection (e.g. [implementing a permit() standard](https://github.com/makerdao/dss/blob/master/src/dai.sol#L117-L141)).\n- **A candidate RelayHub standard:** Our minimal RelayHub.sol can be a candidate for the hard-coded RelayHub in the \\_msgSender() standard.\n- **Minimal proxy contracts:** Our ProxyAccount contracts have minimal functionality (e.g. it can only .call() to a target contract) which makes them easy to audit, reason about and adopt.\n- **Better-than-Ethereum Replay Protection:** We have implemented Nonce, MultiNonce and BitFlip, so the developer can decide if they want to ordered transactions, multiple queues of transactions, or always out-of-order transactions.\n\nThere are several libraries for constructing and signing meta-transactions, but more often than not it is mixed up with the application logic. This repository is protocol and relayer-independent such that it can become a single standard any project can adopt. Hopefully it will make it easier easier for developers to tap into third party relayer APIs and thus no longer need to re-implement the wheel of building reliable transaction infrastructure.\n\n# Table of Contents\n\n- [Getting started](#getting-started)\n- [You are now ready to authorise a meta-transaction!](#you-are-now-ready-to-authorise-a-meta-transaction-)\n  - [Example Echo Contract](#example-echo-contract)\n  - [Proxy Account Contract](#proxy-account-contract)\n  - [RelayHub](#relayhub)\n- [ProxyAccount vs RelayHub](#proxyaccount-vs-relayhub)\n  - [Proxy Account Contract](#proxy-account-contract-1)\n    - [Deploying the proxy contract](#deploying-the-proxy-contract)\n    - [Sign and encode meta-transactions](#sign-and-encode-meta-transactions)\n    - [Sign and encode meta-deployments](#sign-and-encode-meta-deployments)\n  - [Relay Hub](#relay-hub)\n    - [MsgSender.sol](#msgsendersol)\n    - [Sign and encode meta-transactions](#sign-and-encode-meta-transactions-1)\n    - [Sign and encode meta-deployments](#sign-and-encode-meta-deployments-1)\n\n# Getting started\n\nWe assume you have set up your nodejs environment and you simply need to plug-in our library.\n\n1. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. Deciding which network and replay protection to use.\n\nYou will need to import both the ChainID and Replay Protection into your code:\n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\n\nOur library currently supports MAINNET or ROPSTEN.\n\n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\n\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n\n```\n// ReplayProtection\nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\n\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. You need to decide which solution to msg.sender you want to use.\n\nFor the msg.sender solution, we cover [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub) later in the README. If you are unsure which one to use, then **_we recommend proxy account contracts as it works for all existing contracts_**.\n\n4. Time to instantiate the meta-transaction library with your prefered options!\n\nTo instantiate the proxy account forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract.\n\nImportant: It will sign meta-transactions even if the proxy account contract does not exist on the blockchain (e.g. it is not yet deployed). It is possible to send the relayer a meta-deployment (covered soon) to deploy the proxy contract and the meta-transaction. This informs the relayer to meta-deploy the proxy account contract before executing the meta-transaction. So there is no waiting/setup process.\n\nTo instantiate the RelayHub forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst relayHubForwarder = await new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.NONCE,\n    signer\n);\n```\n\nThere is a single instance of the RelayHub on each network and the forwarder links to it. All replay protection is handled by the RelayHub contract and there is no requirement to broadcast/setup in advance. Again, it only works if the target contract supports the \\_msgSender() standard.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nWe will use the Echo smart contract for both examples:\n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## Proxy Account Contract\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the signer's proxy account contract (note: it is very easy to meta-deploy the proxy account contract alongside the first meta-transaction):\n\n```\nconst isProxyDeployed = await forwarder.isContractDeployed();\nif (!isProxyDeployed) {\n    const minimalTx = await forwarder.createProxyContract();\n\n    // For our example we mimic the relayer API with a relayer wallet.\n    const proxyTx = await relayer.sendTransaction({\n      to: minimalTx.to,\n      data: minimalTx.callData,\n    });\n\n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nTo authorise a meta-transaction you must supply:\n\n- **Target** contract's address,\n- **Value** to be sent\n- **Calldata** the function name and its arguments\n\nLet's see a code sample of authorising a meta-transaction for the Echo contract:\n\n```\n// Fetch the contract and the calldata.\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: echo.address,\n    value: new BigNumber(\"0\"),\n    callData,\n});\n\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTxData,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Well done!\n\n## RelayHub\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\n\nconst forwarder = await new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWhile there is no setup/deployment to perform for the signer. It is important that your target contract supports the \\_msgSender() standard. So let's modify the Echo contract to support the standard:\n\n```\npragma solidity ^0.6.2;\nimport \"https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/account/MsgSender.sol\";\n\ncontract Echo is MsgSender {\n    event Broadcast(address signer, string message);\n\n    // In the future we will hard-code the RelayHub\n    // address into MsgSender.sol\n    constructor(address _relayHub) public {\n        relayHub = _relayHub;\n    }\n    function submit(string memory _message) public\n    {\n        address signer = _msgSender();\n        emit Broadcast(signer, _message);\n    }\n}\n```\n\nNow that the target-contract supports the \\_msgSender() standard, you must supply the following to authorise a meta-transaction:\n\n- **Target** contract's address,\n- **Calldata** the function name and its arguments\n\nUnlike proxy account contracts, the RelayHub does not yet support native transfers of ETH. Now that we have the necessary informaton let's send the meta-transaction via the RelayHub:\n\n```\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([message]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: cyberDiceCon.address,\n    callData,\n});\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst receipt = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTxData,\n});\n\nconst tx = await receipt.wait();\n```\n\nWell done!\n\n# ProxyAccount vs RelayHub\n\nAs we mentioned earlier, there are two solutions to the msg.sender problem.\n\n- **Proxy Contract Accounts**: Every user has a proxy contract with a deterministic address. All meta-transactions are sent via the user's proxy account.\n- **RelayHub**: There is no proxy account contracts. The RelayHub appends the signer's address onto the calldata that is sent to the target contract. It requires the target contract to support the \\_msgSender() standard.\n\nWhile proxy contract accounts works for all existing smart contracts, the RelayHub requires the target contract to support the \\_msgSender() standard. If supported, the RelayHub allows the signer's address to be the msg.sender in the target contract. Going forward, we hope that the RelayHub serves as a model and it can later become a precompile/a new opcode in Ethereum.\n\nNote, the RelayHub does not support holding or sending ETH. It is possible to store a balance for each signer, but we opted for a simple/minimalist RelayHub. Find out more at [this issue](https://github.com/anydotcrypto/metatransactions/issues/9) to find out why.\n\n## Proxy Account Contract\n\nThere are two contracts:\n\n- **Proxy Deployer:** Responsible for deploying all proxy account contracts.\n- **Proxy Account:** A proxy contract for a single user.\n\nThe motivation for a ProxyDeployer contract is to act as a global registry for all proxy contracts. It is only responsible for deploying proxy contract addresses and thanks to CREATE2 it ensures all signers have a deterministic proxy address.\n\nThe proxy account contract is responsible for acting as the user's identity to other smart contracts such that msg.sender is the proxy contract's address. Our forwarder library `ProxyAccountForwarder` has methods to support interacting with proxy contracts.\n\n### Deploying the proxy contract\n\nWe must check if the proxy contract is deployed before deciding to deploy it.\n\n```\nconst isDeployed: boolean = await forwarder.isContractDeployed();\nconst minimalTx: MinimalTx = await forwarder.createProxyContract();\n```\n\nThe MinimalTx has the following interface:\n\n```\ninterface MinimalTx {\n  to: string; // Target contract address\n  data: string; // Calldata for the target contract\n}\n```\n\nIt costs approximately ~110k gas (including transaction overhead) to deploy a proxy contract.\n\n### Sign and encode meta-transactions\n\nOur library supports signing the meta-transaction (and taking care of the replay protection under the hood):\n\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nIt returns forward parameters which has the following interface:\n\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address\n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Value in WEI to send\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection\n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. If desired, the forward parameters can be used to directly send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).forward(\n    params.target,\n    params.value,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it may be simpler to encode and send the meta-transaction (e.g. so it satisfies the data field of an Ethereum Transaction):\n\n```\n// Encode calldata for ProxyAccount.forward()\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: metaTxData});\n```\n\n### Sign and encode meta-deployments\n\nA very exciting feature for our library is to support meta-deployments as the proxy contract will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract\n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata:\n\n```\n  const metaDeploymentData = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: metaDeploymentData,\n  });\n```\n\nBut what about the new contract address? How do we derive it?\n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\nWell done! You have leveled up and you can now perform meta-deployments!\n\n## RelayHub\n\nThe RelayHub has a single deployed contract on the network and it is available for all users.\n\nOne way to think about the RelayHub is that it emulates the Ethereum account system. It is only responsible for keeping track of a user's replay protection and verifying their signature. If both conditions pass, then it will append the signer's address to the target contract calldata before forwarding it.\n\nAs we have mentioned several times, the RelayHub is only compatible with contracts that support the \\_msgSender() standard. But the advantage of the RelayHub is that the signer's address is the msg.sender and there is no need to deploy a user-specific contract in advance.\n\n### MsgSender.sol\n\nThe target contract must extend MsgSender.sol and include the contract address of our RelayHub. Let's have a quick look at its code:\n\n```\npragma solidity 0.6.2;\ncontract MsgSender {\n    address public relayHub;\n    function _msgSender() internal view virtual returns (address payable) {\n        if (msg.sender != relayHub) {\n            return msg.sender;\n        } else {\n            return _getRelayedCallSender();\n        }\n    }\n\n    function _getRelayedCallSender() private pure returns (address payable result) {\n        bytes memory array = msg.data;\n        uint256 index = msg.data.length;\n        assembly {\n            result := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)\n        }\n        return result;\n    }\n}\n```\n\nWhen the RelayHub forwards a call to the target contract it will append the signer's address to the msg.data. So the target contract can simply verify that msg.sender is the RelayHub contract address and then extract the signer's address from the msg.sender. It will return the signer's address to the main contract.\n\nThus the target contract must replace msg.sender with \\_msgSender():\n\n```\naddress signer = _msgSender();\n```\n\nThe original idea for msgSender originates from the gas station network (OpenGSN) and we hope to work together with them to standardise the RelayHub.sol.\n\n### Sign and encode meta-transactions\n\nOur library supports signing and encoding the meta-transaction:\n\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nThe forward parameters has the following interface:\n\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address\n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Always set to 0 for the RelayHub\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection\n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. Although it must be mentioned that `value=\"0` as the RelayHub does not support transfering ETH. If desired, the forward parameters can be used to send directly to the relayhub:\n\n```\nconst tx = await relayHubContract.connect(relayer).forward(\n    params.target,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n)\n```\n\nOf course, it may be simpler to encode and send the meta-transaction:\n\n```\n// Encode calldata for RelayHub.forward()\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: metaTxData});\n```\n\n### Sign and encode meta-deployments\n\nA very exciting feature for our library is to support meta-deployments as the RelayHubt will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract\n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the RelayHub:\n\n```\nconst tx = await relayHubContract.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata:\n\n```\n  const metaDeploymentData = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: metaDeploymentData,\n  });\n```\n\nBut what about the new contract address? How do we derive it?\n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\n^^ and that's all for now folks!\n","readmeFilename":"README.md","_id":"@anydotcrypto/metatransactions@0.0.13-8","_nodeVersion":"11.14.0","_npmVersion":"6.14.5","dist":{"integrity":"sha512-s4jQYSbBbb9BM3TNMtx6nSAdmtuBxvHVyzMCKOc5L5WccKq2cEBQG98oiDn+iLTzojTGjY4sS25d0JvpN9STsQ==","shasum":"5b41dfe50509b81ce953f398874b4d6421130cd5","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.13-8.tgz","fileCount":121,"unpackedSize":656956,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJev+0kCRA9TVsSAnZWagAA4PgQAJuK0M+J+GrFgj9y/mvr\nqNLbB9+HKb11yP/qOuFdSjAXn3aei2JrMD0wmxR83Lk71WHSfxl6NyPf9Y1F\nGWJDV5SQfsp+iTPTVBfEl3RSi/M5CFZZaQz4VX/Qhe9Y0kqIq03vBAh2SEDs\nMkxwK1NhpJz+oFHtd93bs1gozH0KkDddA+t82dpYIfYWqPZJa+a2wLnkR5rO\n1/mxcowSA1K8R+iquKeM8Xoufq3qRo6e01rLLvGjNFGDBZLtwOPQ3Id5mI6t\nnnrw/cs0HSrBlRLwLHLKGAPBhDmv/zM2ju6b1Mg3gsQa4qLIabkJECAiz+cO\n7n9IRp0p4wNqqxslvvRZOflQJRrCXZuaZPTZRcHU0wUK9zlu+j/o0kgNQhoA\nnatR7+5M7MQJW6CTexz2nUsq7rBKSwQDBFLbdHLrJlMnd0NXISKfTfuWeYei\noCJNgJLHcWBuvIJ7LXLaX0e/RuEAynWg0bxlnlA6HUeTlP37NUrHYFho7k8R\n31msuE3PtonhbAOpQcd7rBIAgB7UB7wV8uFOaqpF4i1lEjLhJXXdvvv2eycl\n22/iAQ0oLps+DRh5MfyL1kSRKf7PLXpG3DFgJMl5g186SgJUOr8MjY3Hx1Fb\n4/xs4B1BQpVRIAz1LDzw4qnb/0N/tE/lxnNSStXB1L3LXSiBUwrdNlQciWjB\nqyGd\r\n=HcCr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCNHEZG1Fygtduz+kkEehwbnAcgpM7Z3GqMlCrmKU8R9wIhAN9cJSpGonWOX2yVDLD8OZxrD1mKn1Nz0D/18HHM/Ycr"}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"yahgwai","email":"cpbuckland88@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.13-8_1589636388298_0.3564822104783796"},"_hasShrinkwrap":false},"0.0.13-9":{"name":"@anydotcrypto/metatransactions","version":"0.0.13-9","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deploy.ts","generateSeed":"ts-node example/generateSeed.ts","echo-example":"ts-node example/proxyaccounts/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build"},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single RelayHub contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nThis meta-transaction library supports both approaches. We hope it benefits the community in the following way:\n\n- **Ease of adoption:** All smart contracts can support meta-transactions without explicitly handling replay protection (e.g. [implementing a permit() standard](https://github.com/makerdao/dss/blob/master/src/dai.sol#L117-L141)).\n- **A candidate RelayHub standard:** Our minimal RelayHub.sol can be a candidate for the hard-coded RelayHub in the \\_msgSender() standard.\n- **Minimal proxy contracts:** Our ProxyAccount contracts have minimal functionality (e.g. it can only .call() to a target contract) which makes them easy to audit, reason about and adopt.\n- **Better-than-Ethereum Replay Protection:** We have implemented Nonce, MultiNonce and BitFlip, so the developer can decide if they want to ordered transactions, multiple queues of transactions, or always out-of-order transactions.\n\nThere are several libraries for constructing and signing meta-transactions, but more often than not it is mixed up with the application logic. This repository is protocol and relayer-independent such that it can become a single standard any project can adopt. Hopefully it will make it easier easier for developers to tap into third party relayer APIs and thus no longer need to re-implement the wheel of building reliable transaction infrastructure.\n\n# Table of Contents\n\n- [Getting started](#getting-started)\n- [You are now ready to authorise a meta-transaction!](#you-are-now-ready-to-authorise-a-meta-transaction-)\n  - [Example Echo Contract](#example-echo-contract)\n  - [Proxy Account Contract](#proxy-account-contract)\n  - [RelayHub](#relayhub)\n- [ProxyAccount vs RelayHub](#proxyaccount-vs-relayhub)\n  - [Proxy Account Contract](#proxy-account-contract-1)\n    - [Deploying the proxy contract](#deploying-the-proxy-contract)\n    - [Sign and encode meta-transactions](#sign-and-encode-meta-transactions)\n    - [Sign and encode meta-deployments](#sign-and-encode-meta-deployments)\n  - [Relay Hub](#relay-hub)\n    - [MsgSender.sol](#msgsendersol)\n    - [Sign and encode meta-transactions](#sign-and-encode-meta-transactions-1)\n    - [Sign and encode meta-deployments](#sign-and-encode-meta-deployments-1)\n\n# Getting started\n\nWe assume you have set up your nodejs environment and you simply need to plug-in our library.\n\n1. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. Deciding which network and replay protection to use.\n\nYou will need to import both the ChainID and Replay Protection into your code:\n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\n\nOur library currently supports MAINNET or ROPSTEN.\n\n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\n\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n\n```\n// ReplayProtection\nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\n\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. You need to decide which solution to msg.sender you want to use.\n\nFor the msg.sender solution, we cover [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub) later in the README. If you are unsure which one to use, then **_we recommend proxy account contracts as it works for all existing contracts_**.\n\n4. Time to instantiate the meta-transaction library with your prefered options!\n\nTo instantiate the proxy account forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract.\n\nImportant: It will sign meta-transactions even if the proxy account contract does not exist on the blockchain (e.g. it is not yet deployed). It is possible to send the relayer a meta-deployment (covered soon) to deploy the proxy contract and the meta-transaction. This informs the relayer to meta-deploy the proxy account contract before executing the meta-transaction. So there is no waiting/setup process.\n\nTo instantiate the RelayHub forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst relayHubForwarder = await new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.NONCE,\n    signer\n);\n```\n\nThere is a single instance of the RelayHub on each network and the forwarder links to it. All replay protection is handled by the RelayHub contract and there is no requirement to broadcast/setup in advance. Again, it only works if the target contract supports the \\_msgSender() standard.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nWe will use the Echo smart contract for both examples:\n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## Proxy Account Contract\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the signer's proxy account contract (note: it is very easy to meta-deploy the proxy account contract alongside the first meta-transaction):\n\n```\nconst isProxyDeployed = await forwarder.isContractDeployed();\nif (!isProxyDeployed) {\n    const minimalTx = await forwarder.createProxyContract();\n\n    // For our example we mimic the relayer API with a relayer wallet.\n    const proxyTx = await relayer.sendTransaction({\n      to: minimalTx.to,\n      data: minimalTx.callData,\n    });\n\n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nTo authorise a meta-transaction you must supply:\n\n- **Target** contract's address,\n- **Value** to be sent\n- **Calldata** the function name and its arguments\n\nLet's see a code sample of authorising a meta-transaction for the Echo contract:\n\n```\n// Fetch the contract and the calldata.\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: echo.address,\n    value: new BigNumber(\"0\"),\n    callData,\n});\n\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTxData,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Well done!\n\n## RelayHub\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\n\nconst forwarder = await new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWhile there is no setup/deployment to perform for the signer. It is important that your target contract supports the \\_msgSender() standard. So let's modify the Echo contract to support the standard:\n\n```\npragma solidity ^0.6.2;\nimport \"https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/account/MsgSender.sol\";\n\ncontract Echo is MsgSender {\n    event Broadcast(address signer, string message);\n\n    // In the future we will hard-code the RelayHub\n    // address into MsgSender.sol\n    constructor(address _relayHub) public {\n        relayHub = _relayHub;\n    }\n    function submit(string memory _message) public\n    {\n        address signer = _msgSender();\n        emit Broadcast(signer, _message);\n    }\n}\n```\n\nNow that the target-contract supports the \\_msgSender() standard, you must supply the following to authorise a meta-transaction:\n\n- **Target** contract's address,\n- **Calldata** the function name and its arguments\n\nUnlike proxy account contracts, the RelayHub does not yet support native transfers of ETH. Now that we have the necessary informaton let's send the meta-transaction via the RelayHub:\n\n```\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([message]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: cyberDiceCon.address,\n    callData,\n});\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst receipt = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTxData,\n});\n\nconst tx = await receipt.wait();\n```\n\nWell done!\n\n# ProxyAccount vs RelayHub\n\nAs we mentioned earlier, there are two solutions to the msg.sender problem.\n\n- **Proxy Contract Accounts**: Every user has a proxy contract with a deterministic address. All meta-transactions are sent via the user's proxy account.\n- **RelayHub**: There is no proxy account contracts. The RelayHub appends the signer's address onto the calldata that is sent to the target contract. It requires the target contract to support the \\_msgSender() standard.\n\nWhile proxy contract accounts works for all existing smart contracts, the RelayHub requires the target contract to support the \\_msgSender() standard. If supported, the RelayHub allows the signer's address to be the msg.sender in the target contract. Going forward, we hope that the RelayHub serves as a model and it can later become a precompile/a new opcode in Ethereum.\n\nNote, the RelayHub does not support holding or sending ETH. It is possible to store a balance for each signer, but we opted for a simple/minimalist RelayHub. Find out more at [this issue](https://github.com/anydotcrypto/metatransactions/issues/9) to find out why.\n\n## Proxy Account Contract\n\nThere are two contracts:\n\n- **Proxy Deployer:** Responsible for deploying all proxy account contracts.\n- **Proxy Account:** A proxy contract for a single user.\n\nThe motivation for a ProxyDeployer contract is to act as a global registry for all proxy contracts. It is only responsible for deploying proxy contract addresses and thanks to CREATE2 it ensures all signers have a deterministic proxy address.\n\nThe proxy account contract is responsible for acting as the user's identity to other smart contracts such that msg.sender is the proxy contract's address. Our forwarder library `ProxyAccountForwarder` has methods to support interacting with proxy contracts.\n\n### Deploying the proxy contract\n\nWe must check if the proxy contract is deployed before deciding to deploy it.\n\n```\nconst isDeployed: boolean = await forwarder.isContractDeployed();\nconst minimalTx: MinimalTx = await forwarder.createProxyContract();\n```\n\nThe MinimalTx has the following interface:\n\n```\ninterface MinimalTx {\n  to: string; // Target contract address\n  data: string; // Calldata for the target contract\n}\n```\n\nIt costs approximately ~110k gas (including transaction overhead) to deploy a proxy contract.\n\n### Sign and encode meta-transactions\n\nOur library supports signing the meta-transaction (and taking care of the replay protection under the hood):\n\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nIt returns forward parameters which has the following interface:\n\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address\n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Value in WEI to send\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection\n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. If desired, the forward parameters can be used to directly send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).forward(\n    params.target,\n    params.value,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it may be simpler to encode and send the meta-transaction (e.g. so it satisfies the data field of an Ethereum Transaction):\n\n```\n// Encode calldata for ProxyAccount.forward()\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: metaTxData});\n```\n\n### Sign and encode meta-deployments\n\nA very exciting feature for our library is to support meta-deployments as the proxy contract will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract\n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata:\n\n```\n  const metaDeploymentData = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: metaDeploymentData,\n  });\n```\n\nBut what about the new contract address? How do we derive it?\n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\nWell done! You have leveled up and you can now perform meta-deployments!\n\n## RelayHub\n\nThe RelayHub has a single deployed contract on the network and it is available for all users.\n\nOne way to think about the RelayHub is that it emulates the Ethereum account system. It is only responsible for keeping track of a user's replay protection and verifying their signature. If both conditions pass, then it will append the signer's address to the target contract calldata before forwarding it.\n\nAs we have mentioned several times, the RelayHub is only compatible with contracts that support the \\_msgSender() standard. But the advantage of the RelayHub is that the signer's address is the msg.sender and there is no need to deploy a user-specific contract in advance.\n\n### MsgSender.sol\n\nThe target contract must extend MsgSender.sol and include the contract address of our RelayHub. Let's have a quick look at its code:\n\n```\npragma solidity 0.6.2;\ncontract MsgSender {\n    address public relayHub;\n    function _msgSender() internal view virtual returns (address payable) {\n        if (msg.sender != relayHub) {\n            return msg.sender;\n        } else {\n            return _getRelayedCallSender();\n        }\n    }\n\n    function _getRelayedCallSender() private pure returns (address payable result) {\n        bytes memory array = msg.data;\n        uint256 index = msg.data.length;\n        assembly {\n            result := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)\n        }\n        return result;\n    }\n}\n```\n\nWhen the RelayHub forwards a call to the target contract it will append the signer's address to the msg.data. So the target contract can simply verify that msg.sender is the RelayHub contract address and then extract the signer's address from the msg.sender. It will return the signer's address to the main contract.\n\nThus the target contract must replace msg.sender with \\_msgSender():\n\n```\naddress signer = _msgSender();\n```\n\nThe original idea for msgSender originates from the gas station network (OpenGSN) and we hope to work together with them to standardise the RelayHub.sol.\n\n### Sign and encode meta-transactions\n\nOur library supports signing and encoding the meta-transaction:\n\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nThe forward parameters has the following interface:\n\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address\n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Always set to 0 for the RelayHub\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection\n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. Although it must be mentioned that `value=\"0` as the RelayHub does not support transfering ETH. If desired, the forward parameters can be used to send directly to the relayhub:\n\n```\nconst tx = await relayHubContract.connect(relayer).forward(\n    params.target,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n)\n```\n\nOf course, it may be simpler to encode and send the meta-transaction:\n\n```\n// Encode calldata for RelayHub.forward()\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: metaTxData});\n```\n\n### Sign and encode meta-deployments\n\nA very exciting feature for our library is to support meta-deployments as the RelayHubt will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract\n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the RelayHub:\n\n```\nconst tx = await relayHubContract.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata:\n\n```\n  const metaDeploymentData = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: metaDeploymentData,\n  });\n```\n\nBut what about the new contract address? How do we derive it?\n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\n^^ and that's all for now folks!\n","readmeFilename":"README.md","gitHead":"2b08a3255a15e38a0506f082917408830ca2d1e7","_id":"@anydotcrypto/metatransactions@0.0.13-9","_nodeVersion":"11.14.0","_npmVersion":"6.14.5","dist":{"integrity":"sha512-6iEaTVc/apGe3w++DGtc69WBNcxVc8PlTOzMxPpjcve2aeI32PEeWiNcae2co7CLX/mV/Dm3tl3WnWrJggmfkQ==","shasum":"76ea344878af3cdaba86162bd922ba53e220e6a5","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.13-9.tgz","fileCount":121,"unpackedSize":656476,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJewCU9CRA9TVsSAnZWagAAGwoP+QBdC0YdN5g9EeE1zLXd\nwdFFqdf0+QMOPwVz4h0xGTwvmrk6Jnjn9wQGiuxgmte2d2ORWTHcdKN8FPqX\nb4O9KzbsZgfTo2pkerz96ZMYuVf1TJAmBYVolytwF5P+Z0rK2v9Wj6WiX2fp\n0AanWyDknj2sGVmZj9O/sUQeJweIOYNfNKR5DhzVNhHymvU6Rd5oetCsXkhJ\nvip0AmLBnWFJ0Tr/c/4Mut+oy2f9KMXKx+WQExVa4Ca72klsDsHo9y9W6p4X\nWTsjPfdoD4u3TP5pPOWCK9Xuk/sMlFgZdWUosYMaUYN+pN7isMYz36+MkdYH\naoVM4SCZ7vIk6GJQ2r+m8sT1Qt587gHegMALI6VprKQRThXDVzrFMOPkPbBY\n4spioiG1YoBUWxMg+egKDi8TvfZJ9RaJz6SnUPvZqYkgJOmWX1A1s9HZKDgj\ngBEtdG3swtqachLnWJFqozHem8Uo3vxc/TngvZSkRR867uLCfVo4fo34zDcK\nk/klyB76vOi1MgtXnbIFoHBretAaCJu7e6A4kosgHOAHPP3GNvKCDXWgLVH8\n4e3s4Mu+qKKRYBKDakc9SPZwScd+ITIyafhsQpMVWrKXgoDPGObST8BB+r0S\n1lwZCIS0/u37xRd8aj2QXlMOpdjuCY581J2+v4RM28pZ39jrd1tdDSx2gee1\nJ7CW\r\n=INUI\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA+p107TzDJDrOEZJwiRQ7q1hmtQmEbAJeV2yxQMeYqRAiBGW4TtV1NJT6NdxZKf2ckfZW1/HZSLZlDn6bIsxAllkA=="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"yahgwai","email":"cpbuckland88@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.13-9_1589650747865_0.5858987797099242"},"_hasShrinkwrap":false},"0.0.13-10":{"name":"@anydotcrypto/metatransactions","version":"0.0.13-10","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deploy.ts","generateSeed":"ts-node example/generateSeed.ts","echo-example":"ts-node example/proxyaccounts/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build"},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single RelayHub contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nThis meta-transaction library supports both approaches. We hope it benefits the community in the following way:\n\n- **Ease of adoption:** All smart contracts can support meta-transactions without explicitly handling replay protection (e.g. [implementing a permit() standard](https://github.com/makerdao/dss/blob/master/src/dai.sol#L117-L141)).\n- **A candidate RelayHub standard:** Our minimal RelayHub.sol can be a candidate for the hard-coded RelayHub in the \\_msgSender() standard.\n- **Minimal proxy contracts:** Our ProxyAccount contracts have minimal functionality (e.g. it can only .call() to a target contract) which makes them easy to audit, reason about and adopt.\n- **Better-than-Ethereum Replay Protection:** We have implemented Nonce, MultiNonce and BitFlip, so the developer can decide if they want to ordered transactions, multiple queues of transactions, or always out-of-order transactions.\n\nThere are several libraries for constructing and signing meta-transactions, but more often than not it is mixed up with the application logic. This repository is protocol and relayer-independent such that it can become a single standard any project can adopt. Hopefully it will make it easier easier for developers to tap into third party relayer APIs and thus no longer need to re-implement the wheel of building reliable transaction infrastructure.\n\n# Table of Contents\n\n- [Getting started](#getting-started)\n- [You are now ready to authorise a meta-transaction!](#you-are-now-ready-to-authorise-a-meta-transaction-)\n  - [Example Echo Contract](#example-echo-contract)\n  - [Proxy Account Contract](#proxy-account-contract)\n  - [RelayHub](#relayhub)\n- [ProxyAccount vs RelayHub](#proxyaccount-vs-relayhub)\n  - [Proxy Account Contract](#proxy-account-contract-1)\n    - [Deploying the proxy contract](#deploying-the-proxy-contract)\n    - [Sign and encode meta-transactions](#sign-and-encode-meta-transactions)\n    - [Sign and encode meta-deployments](#sign-and-encode-meta-deployments)\n  - [Relay Hub](#relay-hub)\n    - [MsgSender.sol](#msgsendersol)\n    - [Sign and encode meta-transactions](#sign-and-encode-meta-transactions-1)\n    - [Sign and encode meta-deployments](#sign-and-encode-meta-deployments-1)\n\n# Getting started\n\nWe assume you have set up your nodejs environment and you simply need to plug-in our library.\n\n1. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. Deciding which network and replay protection to use.\n\nYou will need to import both the ChainID and Replay Protection into your code:\n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\n\nOur library currently supports MAINNET or ROPSTEN.\n\n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\n\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n\n```\n// ReplayProtection\nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\n\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. You need to decide which solution to msg.sender you want to use.\n\nFor the msg.sender solution, we cover [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub) later in the README. If you are unsure which one to use, then **_we recommend proxy account contracts as it works for all existing contracts_**.\n\n4. Time to instantiate the meta-transaction library with your prefered options!\n\nTo instantiate the proxy account forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract.\n\nImportant: It will sign meta-transactions even if the proxy account contract does not exist on the blockchain (e.g. it is not yet deployed). It is possible to send the relayer a meta-deployment (covered soon) to deploy the proxy contract and the meta-transaction. This informs the relayer to meta-deploy the proxy account contract before executing the meta-transaction. So there is no waiting/setup process.\n\nTo instantiate the RelayHub forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst relayHubForwarder = await new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.NONCE,\n    signer\n);\n```\n\nThere is a single instance of the RelayHub on each network and the forwarder links to it. All replay protection is handled by the RelayHub contract and there is no requirement to broadcast/setup in advance. Again, it only works if the target contract supports the \\_msgSender() standard.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nWe will use the Echo smart contract for both examples:\n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## Proxy Account Contract\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the signer's proxy account contract (note: it is very easy to meta-deploy the proxy account contract alongside the first meta-transaction):\n\n```\nconst isProxyDeployed = await forwarder.isContractDeployed();\nif (!isProxyDeployed) {\n    const minimalTx = await forwarder.createProxyContract();\n\n    // For our example we mimic the relayer API with a relayer wallet.\n    const proxyTx = await relayer.sendTransaction({\n      to: minimalTx.to,\n      data: minimalTx.callData,\n    });\n\n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nTo authorise a meta-transaction you must supply:\n\n- **Target** contract's address,\n- **Value** to be sent\n- **Calldata** the function name and its arguments\n\nLet's see a code sample of authorising a meta-transaction for the Echo contract:\n\n```\n// Fetch the contract and the calldata.\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: echo.address,\n    value: new BigNumber(\"0\"),\n    callData,\n});\n\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTxData,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Well done!\n\n## RelayHub\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\n\nconst forwarder = await new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWhile there is no setup/deployment to perform for the signer. It is important that your target contract supports the \\_msgSender() standard. So let's modify the Echo contract to support the standard:\n\n```\npragma solidity ^0.6.2;\nimport \"https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/account/MsgSender.sol\";\n\ncontract Echo is MsgSender {\n    event Broadcast(address signer, string message);\n\n    // In the future we will hard-code the RelayHub\n    // address into MsgSender.sol\n    constructor(address _relayHub) public {\n        relayHub = _relayHub;\n    }\n    function submit(string memory _message) public\n    {\n        address signer = _msgSender();\n        emit Broadcast(signer, _message);\n    }\n}\n```\n\nNow that the target-contract supports the \\_msgSender() standard, you must supply the following to authorise a meta-transaction:\n\n- **Target** contract's address,\n- **Calldata** the function name and its arguments\n\nUnlike proxy account contracts, the RelayHub does not yet support native transfers of ETH. Now that we have the necessary informaton let's send the meta-transaction via the RelayHub:\n\n```\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([message]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: cyberDiceCon.address,\n    callData,\n});\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst receipt = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTxData,\n});\n\nconst tx = await receipt.wait();\n```\n\nWell done!\n\n# ProxyAccount vs RelayHub\n\nAs we mentioned earlier, there are two solutions to the msg.sender problem.\n\n- **Proxy Contract Accounts**: Every user has a proxy contract with a deterministic address. All meta-transactions are sent via the user's proxy account.\n- **RelayHub**: There is no proxy account contracts. The RelayHub appends the signer's address onto the calldata that is sent to the target contract. It requires the target contract to support the \\_msgSender() standard.\n\nWhile proxy contract accounts works for all existing smart contracts, the RelayHub requires the target contract to support the \\_msgSender() standard. If supported, the RelayHub allows the signer's address to be the msg.sender in the target contract. Going forward, we hope that the RelayHub serves as a model and it can later become a precompile/a new opcode in Ethereum.\n\nNote, the RelayHub does not support holding or sending ETH. It is possible to store a balance for each signer, but we opted for a simple/minimalist RelayHub. Find out more at [this issue](https://github.com/anydotcrypto/metatransactions/issues/9) to find out why.\n\n## Proxy Account Contract\n\nThere are two contracts:\n\n- **Proxy Deployer:** Responsible for deploying all proxy account contracts.\n- **Proxy Account:** A proxy contract for a single user.\n\nThe motivation for a ProxyDeployer contract is to act as a global registry for all proxy contracts. It is only responsible for deploying proxy contract addresses and thanks to CREATE2 it ensures all signers have a deterministic proxy address.\n\nThe proxy account contract is responsible for acting as the user's identity to other smart contracts such that msg.sender is the proxy contract's address. Our forwarder library `ProxyAccountForwarder` has methods to support interacting with proxy contracts.\n\n### Deploying the proxy contract\n\nWe must check if the proxy contract is deployed before deciding to deploy it.\n\n```\nconst isDeployed: boolean = await forwarder.isContractDeployed();\nconst minimalTx: MinimalTx = await forwarder.createProxyContract();\n```\n\nThe MinimalTx has the following interface:\n\n```\ninterface MinimalTx {\n  to: string; // Target contract address\n  data: string; // Calldata for the target contract\n}\n```\n\nIt costs approximately ~110k gas (including transaction overhead) to deploy a proxy contract.\n\n### Sign and encode meta-transactions\n\nOur library supports signing the meta-transaction (and taking care of the replay protection under the hood):\n\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nIt returns forward parameters which has the following interface:\n\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address\n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Value in WEI to send\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection\n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. If desired, the forward parameters can be used to directly send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).forward(\n    params.target,\n    params.value,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it may be simpler to encode and send the meta-transaction (e.g. so it satisfies the data field of an Ethereum Transaction):\n\n```\n// Encode calldata for ProxyAccount.forward()\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: metaTxData});\n```\n\n### Sign and encode meta-deployments\n\nA very exciting feature for our library is to support meta-deployments as the proxy contract will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract\n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata:\n\n```\n  const metaDeploymentData = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: metaDeploymentData,\n  });\n```\n\nBut what about the new contract address? How do we derive it?\n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\nWell done! You have leveled up and you can now perform meta-deployments!\n\n## RelayHub\n\nThe RelayHub has a single deployed contract on the network and it is available for all users.\n\nOne way to think about the RelayHub is that it emulates the Ethereum account system. It is only responsible for keeping track of a user's replay protection and verifying their signature. If both conditions pass, then it will append the signer's address to the target contract calldata before forwarding it.\n\nAs we have mentioned several times, the RelayHub is only compatible with contracts that support the \\_msgSender() standard. But the advantage of the RelayHub is that the signer's address is the msg.sender and there is no need to deploy a user-specific contract in advance.\n\n### MsgSender.sol\n\nThe target contract must extend MsgSender.sol and include the contract address of our RelayHub. Let's have a quick look at its code:\n\n```\npragma solidity 0.6.2;\ncontract MsgSender {\n    address public relayHub;\n    function _msgSender() internal view virtual returns (address payable) {\n        if (msg.sender != relayHub) {\n            return msg.sender;\n        } else {\n            return _getRelayedCallSender();\n        }\n    }\n\n    function _getRelayedCallSender() private pure returns (address payable result) {\n        bytes memory array = msg.data;\n        uint256 index = msg.data.length;\n        assembly {\n            result := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)\n        }\n        return result;\n    }\n}\n```\n\nWhen the RelayHub forwards a call to the target contract it will append the signer's address to the msg.data. So the target contract can simply verify that msg.sender is the RelayHub contract address and then extract the signer's address from the msg.sender. It will return the signer's address to the main contract.\n\nThus the target contract must replace msg.sender with \\_msgSender():\n\n```\naddress signer = _msgSender();\n```\n\nThe original idea for msgSender originates from the gas station network (OpenGSN) and we hope to work together with them to standardise the RelayHub.sol.\n\n### Sign and encode meta-transactions\n\nOur library supports signing and encoding the meta-transaction:\n\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nThe forward parameters has the following interface:\n\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address\n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Always set to 0 for the RelayHub\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection\n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. Although it must be mentioned that `value=\"0` as the RelayHub does not support transfering ETH. If desired, the forward parameters can be used to send directly to the relayhub:\n\n```\nconst tx = await relayHubContract.connect(relayer).forward(\n    params.target,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n)\n```\n\nOf course, it may be simpler to encode and send the meta-transaction:\n\n```\n// Encode calldata for RelayHub.forward()\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: metaTxData});\n```\n\n### Sign and encode meta-deployments\n\nA very exciting feature for our library is to support meta-deployments as the RelayHubt will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract\n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the RelayHub:\n\n```\nconst tx = await relayHubContract.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata:\n\n```\n  const metaDeploymentData = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: metaDeploymentData,\n  });\n```\n\nBut what about the new contract address? How do we derive it?\n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\n^^ and that's all for now folks!\n","readmeFilename":"README.md","gitHead":"0a6cf1507529a8629e19fdf09dcac215b8846498","_id":"@anydotcrypto/metatransactions@0.0.13-10","_nodeVersion":"11.14.0","_npmVersion":"6.14.5","dist":{"integrity":"sha512-JorjZ+PzLGdPGMzYeCEg+P+TAyCGLxwOlUGmk9TbcoR9hyefKqtoGp5xG5zbT7sxwekHGbo5iJ3adiVwWYqy5w==","shasum":"a3c85424a39f75d7dbb328236f37aa8166e477c6","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.13-10.tgz","fileCount":125,"unpackedSize":661313,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJexTQfCRA9TVsSAnZWagAADbwP/RCCQHXoDttz9J7tW1Gk\nI/z1IrXOV0YSwSoxQ7X9I0VJJkPtVS6ayaFf+2hHX499vyYWgBNbVpCVUOhx\nLV4H73IaWIsOnEfLFbxnZ7y/DWmesap029J/KAw2Ksuigb9aF/EfDmubQCOJ\nGbvG55kvcnG6NZ+jpdD/wcGtGEwNWeFKV+gMRx9RRyCdLf3JPShAIsBGgeEn\nJW5nHSV6SyhvDfcuVMVRNLnnuaXYyWT/PHOLdzwJAGbPDj9WLsjQC8Ys5cQ7\n116cjDg/96o1a567/zhU8qeOquJblZENJCIeIvslICZ35HtChYAf6OQQ9s7M\n/m/uNOgr3tdJv9sL8fV/bLyufBPsamhUp7STbzmdV5puqmyj9O1KtaTG6uYw\nBh6tXsSdchbP5e+as9E8BMqUuq3M410QH7twVe0GcSa8W1FCC+NW8K61ZUvf\nmanVwUtXlawtFMwj7Mp/pAF/DFYiZEzb0NIwZTWISpqZsDBmsf70qKqPTTnv\nJQC/5RDHBP2AcLfDqSBywlbvRdBOk2nqUo3OIhFiW2WHRoCJZrRVBbTqNLW/\nv9Hl4RtOWz4Jv6TgScslfzWYyPeioI4MEoUTEo/fsw584cYGX4Cdvit70xjM\nqX/EZyyY/B4bjsdDhlJtq5fDiKeewBFM/DSzztAc6TnLiog+sOyjYx+Y7vlN\nIUa7\r\n=KN2X\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBR07ZEs06ilSvMa5qvsL1uTTT+GNgQbPRnsVFD38OP4AiBdef7/pMoH6CutMy8HA6RbBniYpt2cbWphkCbFOpX9Cw=="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"yahgwai","email":"cpbuckland88@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.13-10_1589982239170_0.4208865193193825"},"_hasShrinkwrap":false},"0.0.13-11":{"name":"@anydotcrypto/metatransactions","version":"0.0.13-11","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deploy.ts","generateSeed":"ts-node example/generateSeed.ts","echo-example":"ts-node example/proxyaccounts/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build"},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single RelayHub contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nThis meta-transaction library supports both approaches. We hope it benefits the community in the following way:\n\n- **Ease of adoption:** All smart contracts can support meta-transactions without explicitly handling replay protection (e.g. [implementing a permit() standard](https://github.com/makerdao/dss/blob/master/src/dai.sol#L117-L141)).\n- **A candidate RelayHub standard:** Our minimal RelayHub.sol can be a candidate for the hard-coded RelayHub in the \\_msgSender() standard.\n- **Minimal proxy contracts:** Our ProxyAccount contracts have minimal functionality (e.g. it can only .call() to a target contract) which makes them easy to audit, reason about and adopt.\n- **Better-than-Ethereum Replay Protection:** We have implemented Nonce, MultiNonce and BitFlip, so the developer can decide if they want to ordered transactions, multiple queues of transactions, or always out-of-order transactions.\n\nThere are several libraries for constructing and signing meta-transactions, but more often than not it is mixed up with the application logic. This repository is protocol and relayer-independent such that it can become a single standard any project can adopt. Hopefully it will make it easier easier for developers to tap into third party relayer APIs and thus no longer need to re-implement the wheel of building reliable transaction infrastructure.\n\n# Table of Contents\n\n- [Getting started](#getting-started)\n- [You are now ready to authorise a meta-transaction!](#you-are-now-ready-to-authorise-a-meta-transaction-)\n  - [Example Echo Contract](#example-echo-contract)\n  - [Proxy Account Contract](#proxy-account-contract)\n  - [RelayHub](#relayhub)\n- [ProxyAccount vs RelayHub](#proxyaccount-vs-relayhub)\n  - [Proxy Account Contract](#proxy-account-contract-1)\n    - [Deploying the proxy contract](#deploying-the-proxy-contract)\n    - [Sign and encode meta-transactions](#sign-and-encode-meta-transactions)\n    - [Sign and encode meta-deployments](#sign-and-encode-meta-deployments)\n  - [Relay Hub](#relay-hub)\n    - [MsgSender.sol](#msgsendersol)\n    - [Sign and encode meta-transactions](#sign-and-encode-meta-transactions-1)\n    - [Sign and encode meta-deployments](#sign-and-encode-meta-deployments-1)\n\n# Getting started\n\nWe assume you have set up your nodejs environment and you simply need to plug-in our library.\n\n1. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. Deciding which network and replay protection to use.\n\nYou will need to import both the ChainID and Replay Protection into your code:\n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\n\nOur library currently supports MAINNET or ROPSTEN.\n\n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\n\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n\n```\n// ReplayProtection\nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\n\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. You need to decide which solution to msg.sender you want to use.\n\nFor the msg.sender solution, we cover [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub) later in the README. If you are unsure which one to use, then **_we recommend proxy account contracts as it works for all existing contracts_**.\n\n4. Time to instantiate the meta-transaction library with your prefered options!\n\nTo instantiate the proxy account forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract.\n\nImportant: It will sign meta-transactions even if the proxy account contract does not exist on the blockchain (e.g. it is not yet deployed). It is possible to send the relayer a meta-deployment (covered soon) to deploy the proxy contract and the meta-transaction. This informs the relayer to meta-deploy the proxy account contract before executing the meta-transaction. So there is no waiting/setup process.\n\nTo instantiate the RelayHub forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst relayHubForwarder = await new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.NONCE,\n    signer\n);\n```\n\nThere is a single instance of the RelayHub on each network and the forwarder links to it. All replay protection is handled by the RelayHub contract and there is no requirement to broadcast/setup in advance. Again, it only works if the target contract supports the \\_msgSender() standard.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nWe will use the Echo smart contract for both examples:\n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## Proxy Account Contract\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the signer's proxy account contract (note: it is very easy to meta-deploy the proxy account contract alongside the first meta-transaction):\n\n```\nconst isProxyDeployed = await forwarder.isContractDeployed();\nif (!isProxyDeployed) {\n    const minimalTx = await forwarder.createProxyContract();\n\n    // For our example we mimic the relayer API with a relayer wallet.\n    const proxyTx = await relayer.sendTransaction({\n      to: minimalTx.to,\n      data: minimalTx.callData,\n    });\n\n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nTo authorise a meta-transaction you must supply:\n\n- **Target** contract's address,\n- **Value** to be sent\n- **Calldata** the function name and its arguments\n\nLet's see a code sample of authorising a meta-transaction for the Echo contract:\n\n```\n// Fetch the contract and the calldata.\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: echo.address,\n    value: new BigNumber(\"0\"),\n    callData,\n});\n\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTxData,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Well done!\n\n## RelayHub\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\n\nconst forwarder = await new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWhile there is no setup/deployment to perform for the signer. It is important that your target contract supports the \\_msgSender() standard. So let's modify the Echo contract to support the standard:\n\n```\npragma solidity ^0.6.2;\nimport \"https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/account/MsgSender.sol\";\n\ncontract Echo is MsgSender {\n    event Broadcast(address signer, string message);\n\n    // In the future we will hard-code the RelayHub\n    // address into MsgSender.sol\n    constructor(address _relayHub) public {\n        relayHub = _relayHub;\n    }\n    function submit(string memory _message) public\n    {\n        address signer = _msgSender();\n        emit Broadcast(signer, _message);\n    }\n}\n```\n\nNow that the target-contract supports the \\_msgSender() standard, you must supply the following to authorise a meta-transaction:\n\n- **Target** contract's address,\n- **Calldata** the function name and its arguments\n\nUnlike proxy account contracts, the RelayHub does not yet support native transfers of ETH. Now that we have the necessary informaton let's send the meta-transaction via the RelayHub:\n\n```\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([message]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: cyberDiceCon.address,\n    callData,\n});\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst receipt = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTxData,\n});\n\nconst tx = await receipt.wait();\n```\n\nWell done!\n\n# ProxyAccount vs RelayHub\n\nAs we mentioned earlier, there are two solutions to the msg.sender problem.\n\n- **Proxy Contract Accounts**: Every user has a proxy contract with a deterministic address. All meta-transactions are sent via the user's proxy account.\n- **RelayHub**: There is no proxy account contracts. The RelayHub appends the signer's address onto the calldata that is sent to the target contract. It requires the target contract to support the \\_msgSender() standard.\n\nWhile proxy contract accounts works for all existing smart contracts, the RelayHub requires the target contract to support the \\_msgSender() standard. If supported, the RelayHub allows the signer's address to be the msg.sender in the target contract. Going forward, we hope that the RelayHub serves as a model and it can later become a precompile/a new opcode in Ethereum.\n\nNote, the RelayHub does not support holding or sending ETH. It is possible to store a balance for each signer, but we opted for a simple/minimalist RelayHub. Find out more at [this issue](https://github.com/anydotcrypto/metatransactions/issues/9) to find out why.\n\n## Proxy Account Contract\n\nThere are two contracts:\n\n- **Proxy Deployer:** Responsible for deploying all proxy account contracts.\n- **Proxy Account:** A proxy contract for a single user.\n\nThe motivation for a ProxyDeployer contract is to act as a global registry for all proxy contracts. It is only responsible for deploying proxy contract addresses and thanks to CREATE2 it ensures all signers have a deterministic proxy address.\n\nThe proxy account contract is responsible for acting as the user's identity to other smart contracts such that msg.sender is the proxy contract's address. Our forwarder library `ProxyAccountForwarder` has methods to support interacting with proxy contracts.\n\n### Deploying the proxy contract\n\nWe must check if the proxy contract is deployed before deciding to deploy it.\n\n```\nconst isDeployed: boolean = await forwarder.isContractDeployed();\nconst minimalTx: MinimalTx = await forwarder.createProxyContract();\n```\n\nThe MinimalTx has the following interface:\n\n```\ninterface MinimalTx {\n  to: string; // Target contract address\n  data: string; // Calldata for the target contract\n}\n```\n\nIt costs approximately ~110k gas (including transaction overhead) to deploy a proxy contract.\n\n### Sign and encode meta-transactions\n\nOur library supports signing the meta-transaction (and taking care of the replay protection under the hood):\n\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nIt returns forward parameters which has the following interface:\n\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address\n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Value in WEI to send\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection\n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. If desired, the forward parameters can be used to directly send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).forward(\n    params.target,\n    params.value,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it may be simpler to encode and send the meta-transaction (e.g. so it satisfies the data field of an Ethereum Transaction):\n\n```\n// Encode calldata for ProxyAccount.forward()\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: metaTxData});\n```\n\n### Sign and encode meta-deployments\n\nA very exciting feature for our library is to support meta-deployments as the proxy contract will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract\n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata:\n\n```\n  const metaDeploymentData = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: metaDeploymentData,\n  });\n```\n\nBut what about the new contract address? How do we derive it?\n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\nWell done! You have leveled up and you can now perform meta-deployments!\n\n## RelayHub\n\nThe RelayHub has a single deployed contract on the network and it is available for all users.\n\nOne way to think about the RelayHub is that it emulates the Ethereum account system. It is only responsible for keeping track of a user's replay protection and verifying their signature. If both conditions pass, then it will append the signer's address to the target contract calldata before forwarding it.\n\nAs we have mentioned several times, the RelayHub is only compatible with contracts that support the \\_msgSender() standard. But the advantage of the RelayHub is that the signer's address is the msg.sender and there is no need to deploy a user-specific contract in advance.\n\n### MsgSender.sol\n\nThe target contract must extend MsgSender.sol and include the contract address of our RelayHub. Let's have a quick look at its code:\n\n```\npragma solidity 0.6.2;\ncontract MsgSender {\n    address public relayHub;\n    function _msgSender() internal view virtual returns (address payable) {\n        if (msg.sender != relayHub) {\n            return msg.sender;\n        } else {\n            return _getRelayedCallSender();\n        }\n    }\n\n    function _getRelayedCallSender() private pure returns (address payable result) {\n        bytes memory array = msg.data;\n        uint256 index = msg.data.length;\n        assembly {\n            result := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)\n        }\n        return result;\n    }\n}\n```\n\nWhen the RelayHub forwards a call to the target contract it will append the signer's address to the msg.data. So the target contract can simply verify that msg.sender is the RelayHub contract address and then extract the signer's address from the msg.sender. It will return the signer's address to the main contract.\n\nThus the target contract must replace msg.sender with \\_msgSender():\n\n```\naddress signer = _msgSender();\n```\n\nThe original idea for msgSender originates from the gas station network (OpenGSN) and we hope to work together with them to standardise the RelayHub.sol.\n\n### Sign and encode meta-transactions\n\nOur library supports signing and encoding the meta-transaction:\n\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nThe forward parameters has the following interface:\n\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address\n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Always set to 0 for the RelayHub\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection\n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. Although it must be mentioned that `value=\"0` as the RelayHub does not support transfering ETH. If desired, the forward parameters can be used to send directly to the relayhub:\n\n```\nconst tx = await relayHubContract.connect(relayer).forward(\n    params.target,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n)\n```\n\nOf course, it may be simpler to encode and send the meta-transaction:\n\n```\n// Encode calldata for RelayHub.forward()\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: metaTxData});\n```\n\n### Sign and encode meta-deployments\n\nA very exciting feature for our library is to support meta-deployments as the RelayHubt will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract\n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the RelayHub:\n\n```\nconst tx = await relayHubContract.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata:\n\n```\n  const metaDeploymentData = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: metaDeploymentData,\n  });\n```\n\nBut what about the new contract address? How do we derive it?\n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\n^^ and that's all for now folks!\n","readmeFilename":"README.md","gitHead":"b6dc6d53ff18e18bda051cddf99031a54e2a6220","_id":"@anydotcrypto/metatransactions@0.0.13-11","_nodeVersion":"11.14.0","_npmVersion":"6.14.5","dist":{"integrity":"sha512-V7JHstpz3QgXC/MgE9aLu0K+BLwYvGB2ek7CuUimiV+9Fr4IP7pgPGsf9QKfo2p3YOS1YnphWiJ7ctlRF2F5Eg==","shasum":"68d6d6b54fa61d44706061ba492da1d1e2df25e5","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.13-11.tgz","fileCount":125,"unpackedSize":669064,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJex/LSCRA9TVsSAnZWagAA4vYP/3v4q31wKOOWDf4xWaIy\nbYNwbj/bhERD8yMnQHrXzjEo6c5E/XMfW+MrhWpOa4OTypLipAQ+6hUEIY+y\nsMRm7qEwPIBc9oSBqM2D1LrV7/bIAOwuy0SpJsYnI4FTL4cHm8gZ6B96nEdH\nFsyN55BWRwkOU4BqVGDC8F8lILbmIIoFRN2JZ54Me5dNXVtuh/QK0HD5VGLd\nazFPxqaBcQQqHypCCa0mwkW+FaxVJvH9ZaXnwhFubE7TV3y2hOwuTUy+JL4+\nAf4BDuoiZhXMmbXCE6k5W/JbbwOXRm/ybmfiGcvkxwJkAjYua4PmqoGI3Duw\nB/mYHhY0x9uHptTg9NhhgMqqyBkxRLl5sgWGDWYvvX0q8lpECxv8hyqqVG4E\n53yIyBlgLqKGkVUk0aPAIWs/Ave5HzYeu8VMCaeD3aShUlQFtBw2Pv8MB6kV\nWRBXTDs4afQatIh/9PMciAr1DLNuipKlqVM/koPloqyoaQNe/3qrY1ZWJAkw\n3AuvWVfgvAH93ggsqFjacZGt8HnLR3loZcIjtNYko4221btFmE1wahs76hbg\nhNuvnHVBmCK1lIgHXInQ7f+lALI6KmBwoCosx4WgOiel2JP322uPihaF9aSO\n8KG2qcKFBoG38P6iO3U8sgdOyQPY0UHBTX1qkJ97+iRBJsiGzGPcJJqgErvU\nTPiE\r\n=7BpG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD/xWlu9PVS73HyyijKgSZD4N+qOLy2RmX6QITbnRVUgQIgXMe2z3CQySigAy5e4jBjZvCMpq2EJ0g0binsBxz3goM="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"yahgwai","email":"cpbuckland88@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.13-11_1590162130009_0.003010180595986567"},"_hasShrinkwrap":false},"0.0.13-12":{"name":"@anydotcrypto/metatransactions","version":"0.0.13-12","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deploy.ts","generateSeed":"ts-node example/generateSeed.ts","echo-example":"ts-node example/proxyaccounts/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build"},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single RelayHub contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nThis meta-transaction library supports both approaches. We hope it benefits the community in the following way:\n\n- **Ease of adoption:** All smart contracts can support meta-transactions without explicitly handling replay protection (e.g. [implementing a permit() standard](https://github.com/makerdao/dss/blob/master/src/dai.sol#L117-L141)).\n- **A candidate RelayHub standard:** Our minimal RelayHub.sol can be a candidate for the hard-coded RelayHub in the \\_msgSender() standard.\n- **Minimal proxy contracts:** Our ProxyAccount contracts have minimal functionality (e.g. it can only .call() to a target contract) which makes them easy to audit, reason about and adopt.\n- **Better-than-Ethereum Replay Protection:** We have implemented Nonce, MultiNonce and BitFlip, so the developer can decide if they want to ordered transactions, multiple queues of transactions, or always out-of-order transactions.\n\nThere are several libraries for constructing and signing meta-transactions, but more often than not it is mixed up with the application logic. This repository is protocol and relayer-independent such that it can become a single standard any project can adopt. Hopefully it will make it easier easier for developers to tap into third party relayer APIs and thus no longer need to re-implement the wheel of building reliable transaction infrastructure.\n\n# Table of Contents\n\n- [Getting started](#getting-started)\n- [You are now ready to authorise a meta-transaction!](#you-are-now-ready-to-authorise-a-meta-transaction-)\n  - [Example Echo Contract](#example-echo-contract)\n  - [Proxy Account Contract](#proxy-account-contract)\n  - [RelayHub](#relayhub)\n- [ProxyAccount vs RelayHub](#proxyaccount-vs-relayhub)\n  - [Proxy Account Contract](#proxy-account-contract-1)\n    - [Deploying the proxy contract](#deploying-the-proxy-contract)\n    - [Sign and encode meta-transactions](#sign-and-encode-meta-transactions)\n    - [Sign and encode meta-deployments](#sign-and-encode-meta-deployments)\n  - [Relay Hub](#relay-hub)\n    - [MsgSender.sol](#msgsendersol)\n    - [Sign and encode meta-transactions](#sign-and-encode-meta-transactions-1)\n    - [Sign and encode meta-deployments](#sign-and-encode-meta-deployments-1)\n\n# Getting started\n\nWe assume you have set up your nodejs environment and you simply need to plug-in our library.\n\n1. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. Deciding which network and replay protection to use.\n\nYou will need to import both the ChainID and Replay Protection into your code:\n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\n\nOur library currently supports MAINNET or ROPSTEN.\n\n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\n\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n\n```\n// ReplayProtection\nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\n\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. You need to decide which solution to msg.sender you want to use.\n\nFor the msg.sender solution, we cover [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub) later in the README. If you are unsure which one to use, then **_we recommend proxy account contracts as it works for all existing contracts_**.\n\n4. Time to instantiate the meta-transaction library with your prefered options!\n\nTo instantiate the proxy account forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract.\n\nImportant: It will sign meta-transactions even if the proxy account contract does not exist on the blockchain (e.g. it is not yet deployed). It is possible to send the relayer a meta-deployment (covered soon) to deploy the proxy contract and the meta-transaction. This informs the relayer to meta-deploy the proxy account contract before executing the meta-transaction. So there is no waiting/setup process.\n\nTo instantiate the RelayHub forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst relayHubForwarder = await new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.NONCE,\n    signer\n);\n```\n\nThere is a single instance of the RelayHub on each network and the forwarder links to it. All replay protection is handled by the RelayHub contract and there is no requirement to broadcast/setup in advance. Again, it only works if the target contract supports the \\_msgSender() standard.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nWe will use the Echo smart contract for both examples:\n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## Proxy Account Contract\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the signer's proxy account contract (note: it is very easy to meta-deploy the proxy account contract alongside the first meta-transaction):\n\n```\nconst isProxyDeployed = await forwarder.isContractDeployed();\nif (!isProxyDeployed) {\n    const minimalTx = await forwarder.createProxyContract();\n\n    // For our example we mimic the relayer API with a relayer wallet.\n    const proxyTx = await relayer.sendTransaction({\n      to: minimalTx.to,\n      data: minimalTx.callData,\n    });\n\n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nTo authorise a meta-transaction you must supply:\n\n- **Target** contract's address,\n- **Value** to be sent\n- **Calldata** the function name and its arguments\n\nLet's see a code sample of authorising a meta-transaction for the Echo contract:\n\n```\n// Fetch the contract and the calldata.\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: echo.address,\n    value: new BigNumber(\"0\"),\n    callData,\n});\n\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTxData,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Well done!\n\n## RelayHub\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\n\nconst forwarder = await new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWhile there is no setup/deployment to perform for the signer. It is important that your target contract supports the \\_msgSender() standard. So let's modify the Echo contract to support the standard:\n\n```\npragma solidity ^0.6.2;\nimport \"https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/account/MsgSender.sol\";\n\ncontract Echo is MsgSender {\n    event Broadcast(address signer, string message);\n\n    // In the future we will hard-code the RelayHub\n    // address into MsgSender.sol\n    constructor(address _relayHub) public {\n        relayHub = _relayHub;\n    }\n    function submit(string memory _message) public\n    {\n        address signer = _msgSender();\n        emit Broadcast(signer, _message);\n    }\n}\n```\n\nNow that the target-contract supports the \\_msgSender() standard, you must supply the following to authorise a meta-transaction:\n\n- **Target** contract's address,\n- **Calldata** the function name and its arguments\n\nUnlike proxy account contracts, the RelayHub does not yet support native transfers of ETH. Now that we have the necessary informaton let's send the meta-transaction via the RelayHub:\n\n```\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([message]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: cyberDiceCon.address,\n    callData,\n});\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst receipt = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTxData,\n});\n\nconst tx = await receipt.wait();\n```\n\nWell done!\n\n# ProxyAccount vs RelayHub\n\nAs we mentioned earlier, there are two solutions to the msg.sender problem.\n\n- **Proxy Contract Accounts**: Every user has a proxy contract with a deterministic address. All meta-transactions are sent via the user's proxy account.\n- **RelayHub**: There is no proxy account contracts. The RelayHub appends the signer's address onto the calldata that is sent to the target contract. It requires the target contract to support the \\_msgSender() standard.\n\nWhile proxy contract accounts works for all existing smart contracts, the RelayHub requires the target contract to support the \\_msgSender() standard. If supported, the RelayHub allows the signer's address to be the msg.sender in the target contract. Going forward, we hope that the RelayHub serves as a model and it can later become a precompile/a new opcode in Ethereum.\n\nNote, the RelayHub does not support holding or sending ETH. It is possible to store a balance for each signer, but we opted for a simple/minimalist RelayHub. Find out more at [this issue](https://github.com/anydotcrypto/metatransactions/issues/9) to find out why.\n\n## Proxy Account Contract\n\nThere are two contracts:\n\n- **Proxy Deployer:** Responsible for deploying all proxy account contracts.\n- **Proxy Account:** A proxy contract for a single user.\n\nThe motivation for a ProxyDeployer contract is to act as a global registry for all proxy contracts. It is only responsible for deploying proxy contract addresses and thanks to CREATE2 it ensures all signers have a deterministic proxy address.\n\nThe proxy account contract is responsible for acting as the user's identity to other smart contracts such that msg.sender is the proxy contract's address. Our forwarder library `ProxyAccountForwarder` has methods to support interacting with proxy contracts.\n\n### Deploying the proxy contract\n\nWe must check if the proxy contract is deployed before deciding to deploy it.\n\n```\nconst isDeployed: boolean = await forwarder.isContractDeployed();\nconst minimalTx: MinimalTx = await forwarder.createProxyContract();\n```\n\nThe MinimalTx has the following interface:\n\n```\ninterface MinimalTx {\n  to: string; // Target contract address\n  data: string; // Calldata for the target contract\n}\n```\n\nIt costs approximately ~110k gas (including transaction overhead) to deploy a proxy contract.\n\n### Sign and encode meta-transactions\n\nOur library supports signing the meta-transaction (and taking care of the replay protection under the hood):\n\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nIt returns forward parameters which has the following interface:\n\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address\n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Value in WEI to send\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection\n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. If desired, the forward parameters can be used to directly send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).forward(\n    params.target,\n    params.value,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it may be simpler to encode and send the meta-transaction (e.g. so it satisfies the data field of an Ethereum Transaction):\n\n```\n// Encode calldata for ProxyAccount.forward()\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: metaTxData});\n```\n\n### Sign and encode meta-deployments\n\nA very exciting feature for our library is to support meta-deployments as the proxy contract will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract\n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata:\n\n```\n  const metaDeploymentData = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: metaDeploymentData,\n  });\n```\n\nBut what about the new contract address? How do we derive it?\n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\nWell done! You have leveled up and you can now perform meta-deployments!\n\n## RelayHub\n\nThe RelayHub has a single deployed contract on the network and it is available for all users.\n\nOne way to think about the RelayHub is that it emulates the Ethereum account system. It is only responsible for keeping track of a user's replay protection and verifying their signature. If both conditions pass, then it will append the signer's address to the target contract calldata before forwarding it.\n\nAs we have mentioned several times, the RelayHub is only compatible with contracts that support the \\_msgSender() standard. But the advantage of the RelayHub is that the signer's address is the msg.sender and there is no need to deploy a user-specific contract in advance.\n\n### MsgSender.sol\n\nThe target contract must extend MsgSender.sol and include the contract address of our RelayHub. Let's have a quick look at its code:\n\n```\npragma solidity 0.6.2;\ncontract MsgSender {\n    address public relayHub;\n    function _msgSender() internal view virtual returns (address payable) {\n        if (msg.sender != relayHub) {\n            return msg.sender;\n        } else {\n            return _getRelayedCallSender();\n        }\n    }\n\n    function _getRelayedCallSender() private pure returns (address payable result) {\n        bytes memory array = msg.data;\n        uint256 index = msg.data.length;\n        assembly {\n            result := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)\n        }\n        return result;\n    }\n}\n```\n\nWhen the RelayHub forwards a call to the target contract it will append the signer's address to the msg.data. So the target contract can simply verify that msg.sender is the RelayHub contract address and then extract the signer's address from the msg.sender. It will return the signer's address to the main contract.\n\nThus the target contract must replace msg.sender with \\_msgSender():\n\n```\naddress signer = _msgSender();\n```\n\nThe original idea for msgSender originates from the gas station network (OpenGSN) and we hope to work together with them to standardise the RelayHub.sol.\n\n### Sign and encode meta-transactions\n\nOur library supports signing and encoding the meta-transaction:\n\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nThe forward parameters has the following interface:\n\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address\n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Always set to 0 for the RelayHub\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection\n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. Although it must be mentioned that `value=\"0` as the RelayHub does not support transfering ETH. If desired, the forward parameters can be used to send directly to the relayhub:\n\n```\nconst tx = await relayHubContract.connect(relayer).forward(\n    params.target,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n)\n```\n\nOf course, it may be simpler to encode and send the meta-transaction:\n\n```\n// Encode calldata for RelayHub.forward()\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: metaTxData});\n```\n\n### Sign and encode meta-deployments\n\nA very exciting feature for our library is to support meta-deployments as the RelayHubt will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract\n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the RelayHub:\n\n```\nconst tx = await relayHubContract.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata:\n\n```\n  const metaDeploymentData = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: metaDeploymentData,\n  });\n```\n\nBut what about the new contract address? How do we derive it?\n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\n^^ and that's all for now folks!\n","readmeFilename":"README.md","gitHead":"f3ddc5e5b43eb4d42a526b255be21dc8b74407cc","_id":"@anydotcrypto/metatransactions@0.0.13-12","_nodeVersion":"11.14.0","_npmVersion":"6.14.5","dist":{"integrity":"sha512-8uaA06ikHC56e8TH+CwvMS3QyEvpy9zGaR+Ilxd49hQPqxcoCz1ilmVlH6Tk/UgTPBjkVqfzBxMNOdyMySbGGw==","shasum":"4438ac7061218235664f3175b2a83360400f60b6","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.13-12.tgz","fileCount":125,"unpackedSize":674035,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJez9SkCRA9TVsSAnZWagAAfgoQAJZTrZ6WcxT9DWY8faEB\nlSco6L1pM6qhud3vYmhzPya7i3dDvhDOUOLJNg1ku4Yu5kF4ts8Y8mrt0lSL\n6cSBxmLj1WUD002cQ6xvddhMKSO9pW8Y2a1kRxK3EdkBvVnaRPWXkxSsr/hK\nTux7CSjagqdrFI3SIzxwFeBWheU55bU5hQooPIJxDWVRjfwDyEyP6N0UTRis\nWPxN6Xl65u4TGOOK+8pIHFCyOfHWRi/+866JIV8QjzRQKjoQ5APIxeosmjL7\nvAwh48hA0vY6tzo1LWU121gkg+Uwzim3Qr8a+SX+A6pTnXFYrZtVkRecgzJ2\nzBgLy+N0WSZVqdWGcDwWbHWW4n6VpDma+A2erjt7aeQLH9YNPs5MM7JznQK4\nJm5kN5ZVPK3KpJkjya+j3tL0QDNsn6XeDRT+lcU5WSotBk6sb81OhR089GwY\nhFstH9xS9tRT8m5TfE0bpyCyMhsyhJf1Bp7U2C2bNeX3TGUGvTGZqooNuXJO\n8K5m4dEHLe1nXueEqUJZxRoc0YhFUEsJb7KP0NmnlqOj+lSbUygZMXg8hInB\nQgvpBDDdglp6uiPt9FGN3dnJkyhZvfAdW6BcsWafoXk2gUZSG5eX601IsKBq\nhIKQV1AReJKnDt39Wt8x+iYKSxe+ozw48m7rhARX6T53Rti8V7EhVS+dUa5Z\nUpzk\r\n=YRpj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDsfI2y24KhJ8DkWPgthFRCcRkb/G9xQ4cZmwdN4HIDdQIhAO6PXG4S7RpnzcnwX4ZHL33KZYN8gA98dVoGkRyV+hN4"}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"yahgwai","email":"cpbuckland88@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.13-12_1590678691324_0.027330085771654744"},"_hasShrinkwrap":false},"0.0.13-13":{"name":"@anydotcrypto/metatransactions","version":"0.0.13-13","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deploy.ts","generateSeed":"ts-node example/generateSeed.ts","echo-example":"ts-node example/proxyaccounts/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build"},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single RelayHub contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nThis meta-transaction library supports both approaches. We hope it benefits the community in the following way:\n\n- **Ease of adoption:** All smart contracts can support meta-transactions without explicitly handling replay protection (e.g. [implementing a permit() standard](https://github.com/makerdao/dss/blob/master/src/dai.sol#L117-L141)).\n- **A candidate RelayHub standard:** Our minimal RelayHub.sol can be a candidate for the hard-coded RelayHub in the \\_msgSender() standard.\n- **Minimal proxy contracts:** Our ProxyAccount contracts have minimal functionality (e.g. it can only .call() to a target contract) which makes them easy to audit, reason about and adopt.\n- **Better-than-Ethereum Replay Protection:** We have implemented Nonce, MultiNonce and BitFlip, so the developer can decide if they want to ordered transactions, multiple queues of transactions, or always out-of-order transactions.\n\nThere are several libraries for constructing and signing meta-transactions, but more often than not it is mixed up with the application logic. This repository is protocol and relayer-independent such that it can become a single standard any project can adopt. Hopefully it will make it easier easier for developers to tap into third party relayer APIs and thus no longer need to re-implement the wheel of building reliable transaction infrastructure.\n\n# Table of Contents\n\n- [Getting started](#getting-started)\n- [You are now ready to authorise a meta-transaction!](#you-are-now-ready-to-authorise-a-meta-transaction-)\n  - [Example Echo Contract](#example-echo-contract)\n  - [Proxy Account Contract](#proxy-account-contract)\n  - [RelayHub](#relayhub)\n- [ProxyAccount vs RelayHub](#proxyaccount-vs-relayhub)\n  - [Proxy Account Contract](#proxy-account-contract-1)\n    - [Deploying the proxy contract](#deploying-the-proxy-contract)\n    - [Sign and encode meta-transactions](#sign-and-encode-meta-transactions)\n    - [Sign and encode meta-deployments](#sign-and-encode-meta-deployments)\n  - [Relay Hub](#relay-hub)\n    - [MsgSender.sol](#msgsendersol)\n    - [Sign and encode meta-transactions](#sign-and-encode-meta-transactions-1)\n    - [Sign and encode meta-deployments](#sign-and-encode-meta-deployments-1)\n\n# Getting started\n\nWe assume you have set up your nodejs environment and you simply need to plug-in our library.\n\n1. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. Deciding which network and replay protection to use.\n\nYou will need to import both the ChainID and Replay Protection into your code:\n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\n\nOur library currently supports MAINNET or ROPSTEN.\n\n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\n\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n\n```\n// ReplayProtection\nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\n\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. You need to decide which solution to msg.sender you want to use.\n\nFor the msg.sender solution, we cover [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub) later in the README. If you are unsure which one to use, then **_we recommend proxy account contracts as it works for all existing contracts_**.\n\n4. Time to instantiate the meta-transaction library with your prefered options!\n\nTo instantiate the proxy account forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract.\n\nImportant: It will sign meta-transactions even if the proxy account contract does not exist on the blockchain (e.g. it is not yet deployed). It is possible to send the relayer a meta-deployment (covered soon) to deploy the proxy contract and the meta-transaction. This informs the relayer to meta-deploy the proxy account contract before executing the meta-transaction. So there is no waiting/setup process.\n\nTo instantiate the RelayHub forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst relayHubForwarder = await new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.NONCE,\n    signer\n);\n```\n\nThere is a single instance of the RelayHub on each network and the forwarder links to it. All replay protection is handled by the RelayHub contract and there is no requirement to broadcast/setup in advance. Again, it only works if the target contract supports the \\_msgSender() standard.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nWe will use the Echo smart contract for both examples:\n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## Proxy Account Contract\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the signer's proxy account contract (note: it is very easy to meta-deploy the proxy account contract alongside the first meta-transaction):\n\n```\nconst isProxyDeployed = await forwarder.isContractDeployed();\nif (!isProxyDeployed) {\n    const minimalTx = await forwarder.createProxyContract();\n\n    // For our example we mimic the relayer API with a relayer wallet.\n    const proxyTx = await relayer.sendTransaction({\n      to: minimalTx.to,\n      data: minimalTx.callData,\n    });\n\n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nTo authorise a meta-transaction you must supply:\n\n- **Target** contract's address,\n- **Value** to be sent\n- **Calldata** the function name and its arguments\n\nLet's see a code sample of authorising a meta-transaction for the Echo contract:\n\n```\n// Fetch the contract and the calldata.\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: echo.address,\n    value: new BigNumber(\"0\"),\n    callData,\n});\n\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTxData,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Well done!\n\n## RelayHub\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\n\nconst forwarder = await new RelayHubForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWhile there is no setup/deployment to perform for the signer. It is important that your target contract supports the \\_msgSender() standard. So let's modify the Echo contract to support the standard:\n\n```\npragma solidity ^0.6.2;\nimport \"https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/account/MsgSender.sol\";\n\ncontract Echo is MsgSender {\n    event Broadcast(address signer, string message);\n\n    // In the future we will hard-code the RelayHub\n    // address into MsgSender.sol\n    constructor(address _relayHub) public {\n        relayHub = _relayHub;\n    }\n    function submit(string memory _message) public\n    {\n        address signer = _msgSender();\n        emit Broadcast(signer, _message);\n    }\n}\n```\n\nNow that the target-contract supports the \\_msgSender() standard, you must supply the following to authorise a meta-transaction:\n\n- **Target** contract's address,\n- **Calldata** the function name and its arguments\n\nUnlike proxy account contracts, the RelayHub does not yet support native transfers of ETH. Now that we have the necessary informaton let's send the meta-transaction via the RelayHub:\n\n```\nconst echo = new EchoFactory(user).attach(\"\");\nconst callData = echo.interface.functions.submit.encode([message]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    target: cyberDiceCon.address,\n    callData,\n});\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    metaTx\n);\n\nconst receipt = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTxData,\n});\n\nconst tx = await receipt.wait();\n```\n\nWell done!\n\n# ProxyAccount vs RelayHub\n\nAs we mentioned earlier, there are two solutions to the msg.sender problem.\n\n- **Proxy Contract Accounts**: Every user has a proxy contract with a deterministic address. All meta-transactions are sent via the user's proxy account.\n- **RelayHub**: There is no proxy account contracts. The RelayHub appends the signer's address onto the calldata that is sent to the target contract. It requires the target contract to support the \\_msgSender() standard.\n\nWhile proxy contract accounts works for all existing smart contracts, the RelayHub requires the target contract to support the \\_msgSender() standard. If supported, the RelayHub allows the signer's address to be the msg.sender in the target contract. Going forward, we hope that the RelayHub serves as a model and it can later become a precompile/a new opcode in Ethereum.\n\nNote, the RelayHub does not support holding or sending ETH. It is possible to store a balance for each signer, but we opted for a simple/minimalist RelayHub. Find out more at [this issue](https://github.com/anydotcrypto/metatransactions/issues/9) to find out why.\n\n## Proxy Account Contract\n\nThere are two contracts:\n\n- **Proxy Deployer:** Responsible for deploying all proxy account contracts.\n- **Proxy Account:** A proxy contract for a single user.\n\nThe motivation for a ProxyDeployer contract is to act as a global registry for all proxy contracts. It is only responsible for deploying proxy contract addresses and thanks to CREATE2 it ensures all signers have a deterministic proxy address.\n\nThe proxy account contract is responsible for acting as the user's identity to other smart contracts such that msg.sender is the proxy contract's address. Our forwarder library `ProxyAccountForwarder` has methods to support interacting with proxy contracts.\n\n### Deploying the proxy contract\n\nWe must check if the proxy contract is deployed before deciding to deploy it.\n\n```\nconst isDeployed: boolean = await forwarder.isContractDeployed();\nconst minimalTx: MinimalTx = await forwarder.createProxyContract();\n```\n\nThe MinimalTx has the following interface:\n\n```\ninterface MinimalTx {\n  to: string; // Target contract address\n  data: string; // Calldata for the target contract\n}\n```\n\nIt costs approximately ~110k gas (including transaction overhead) to deploy a proxy contract.\n\n### Sign and encode meta-transactions\n\nOur library supports signing the meta-transaction (and taking care of the replay protection under the hood):\n\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nIt returns forward parameters which has the following interface:\n\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address\n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Value in WEI to send\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection\n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. If desired, the forward parameters can be used to directly send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).forward(\n    params.target,\n    params.value,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it may be simpler to encode and send the meta-transaction (e.g. so it satisfies the data field of an Ethereum Transaction):\n\n```\n// Encode calldata for ProxyAccount.forward()\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: metaTxData});\n```\n\n### Sign and encode meta-deployments\n\nA very exciting feature for our library is to support meta-deployments as the proxy contract will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract\n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the proxy account:\n\n```\nconst tx = await proxyAccount.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata:\n\n```\n  const metaDeploymentData = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: metaDeploymentData,\n  });\n```\n\nBut what about the new contract address? How do we derive it?\n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\nWell done! You have leveled up and you can now perform meta-deployments!\n\n## RelayHub\n\nThe RelayHub has a single deployed contract on the network and it is available for all users.\n\nOne way to think about the RelayHub is that it emulates the Ethereum account system. It is only responsible for keeping track of a user's replay protection and verifying their signature. If both conditions pass, then it will append the signer's address to the target contract calldata before forwarding it.\n\nAs we have mentioned several times, the RelayHub is only compatible with contracts that support the \\_msgSender() standard. But the advantage of the RelayHub is that the signer's address is the msg.sender and there is no need to deploy a user-specific contract in advance.\n\n### MsgSender.sol\n\nThe target contract must extend MsgSender.sol and include the contract address of our RelayHub. Let's have a quick look at its code:\n\n```\npragma solidity 0.6.2;\ncontract MsgSender {\n    address public relayHub;\n    function _msgSender() internal view virtual returns (address payable) {\n        if (msg.sender != relayHub) {\n            return msg.sender;\n        } else {\n            return _getRelayedCallSender();\n        }\n    }\n\n    function _getRelayedCallSender() private pure returns (address payable result) {\n        bytes memory array = msg.data;\n        uint256 index = msg.data.length;\n        assembly {\n            result := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)\n        }\n        return result;\n    }\n}\n```\n\nWhen the RelayHub forwards a call to the target contract it will append the signer's address to the msg.data. So the target contract can simply verify that msg.sender is the RelayHub contract address and then extract the signer's address from the msg.sender. It will return the signer's address to the main contract.\n\nThus the target contract must replace msg.sender with \\_msgSender():\n\n```\naddress signer = _msgSender();\n```\n\nThe original idea for msgSender originates from the gas station network (OpenGSN) and we hope to work together with them to standardise the RelayHub.sol.\n\n### Sign and encode meta-transactions\n\nOur library supports signing and encoding the meta-transaction:\n\n```\nconst callData = echo.interface.functions.submit.encode([message]);\n\nconst params: ForwardParams = await forwarder.signMetaTransaction( {to: echo.address, data: callData);\n```\n\nThe forward parameters has the following interface:\n\n```\ninterface ForwardParams {\n  to: string; // Proxy contract address\n  signer: string; // Signer's address\n  target: string; // Target contract address (echo)\n  value: string; // Always set to 0 for the RelayHub\n  data: string; // Target contract calldata\n  replayProtection: string; // Encoded replay protection\n  replayProtectionAuthority: string; // Replay Protection Authority (Advanced feature)\n  chainId: number; // Chain ID (MAINNET or ROPSTEN)\n  signature: string; // Signer's signature\n}\n```\n\nAs we can see in the forward parameters, the library takes care of fetching the latest replay protection and encoding it for use. Although it must be mentioned that `value=\"0` as the RelayHub does not support transfering ETH. If desired, the forward parameters can be used to send directly to the relayhub:\n\n```\nconst tx = await relayHubContract.connect(relayer).forward(\n    params.target,\n    params.data,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n)\n```\n\nOf course, it may be simpler to encode and send the meta-transaction:\n\n```\n// Encode calldata for RelayHub.forward()\nconst metaTxData = await forwarder.encodeSignedMetaTransaction(\n    params\n\n// Sent directly to the ProxyAccount with the nencoded calldata\nconst tx = await relayer.sendTransaction({to: params.to, data: metaTxData});\n```\n\n### Sign and encode meta-deployments\n\nA very exciting feature for our library is to support meta-deployments as the RelayHubt will deploy all contracts via CREATE2. Let's dive in:\n\n```\nconst echoFactory = new EchoFactory(user);\nconst initCode = competitionFactory.getDeployTransaction().data! as string;\n\nconst params: DeploymentParams = await forwarder.signMetaDeployment(\n    initCode\n);\n```\n\nThe deployment parameters has the following interface:\n\n```\ninterface DeploymentParams {\n  to: string; // Proxy contract account\n  signer: string; // Signer's address\n  initCode: string; // Bytecode for the contract\n  replayProtection: string; // Encoded Replay Protection\n  replayProtectionAuthority: string; // Replay Protection Authority (advanced feature)\n  chainId: number; // ChainID\n  signature: string; // Signature\n}\n```\n\nAgain, as we can see, the library handles all replay protection for the user. If desired, the deployment parameters can be used directly to send it to the RelayHub:\n\n```\nconst tx = await relayHubContract.connect(relayer).deployContract(\n    params.initCode,\n    params.replayProtection,\n    params.replayProtectionAuthority,\n    params.signer,\n    params.signature\n);\n```\n\nOf course, it might just be easier to encode and send the calldata:\n\n```\n  const metaDeploymentData = await forwarder.encodeSignedMetaDeployment(\n    params\n  );\n  const tx = await relayer.sendTransaction({\n    to: params.to,\n    data: metaDeploymentData,\n  });\n```\n\nBut what about the new contract address? How do we derive it?\n\n```\nconst echoAddress = forwarder.buildDeployedContractAddress(params);\n```\n\n^^ and that's all for now folks!\n","readmeFilename":"README.md","gitHead":"ac72b37f93136741e98f0025c1e5f2988e489f68","_id":"@anydotcrypto/metatransactions@0.0.13-13","_nodeVersion":"11.14.0","_npmVersion":"6.14.5","dist":{"integrity":"sha512-lup01cdoUFmY/RxxMh5/GBqpimOzHa+gKiuxhynkLFW17g9rL8l0WYCFg8OdGBrmqEt5Y1tSYB2hKTqNab9nXw==","shasum":"dbd1ab362db859f8cf8cf205b12553a716f98ca3","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.13-13.tgz","fileCount":125,"unpackedSize":673606,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJez/GqCRA9TVsSAnZWagAAcYsP/0o98H7wtmAEQQiQlf23\ntjEbAG6oIsNIoZ6xUgxxyL1FdMW2qpPX0L1lm0ZEbkNcOGs9kUvomt5rsjSA\nSoyn+rf0u7zaSwvnmCqmm2EFMT1S1l6xoubVgv3pqFT9pFO13Gkd5MuXj9vC\nGbyli3bsQZcy/vQTNS1owOK7lzE6dRbDxxFPkjRj4QUK0BKE9gXnNBPXnaGt\nwRr1V43jkJe0Acr/ao7cXaHV9xe0XvXAJt82J3mvPiPJO2wSvLNmuUPCBARt\n2t4tQR4+Xroy3TZA8Iz8rlzoD/uImB2FcqNIg+SlenZ3SS2U8Cv61yPrK4SG\na+mIYDHVlg91NMVsZnsK3xuYIwOyA1gtieYOJ7tVGXhIrc9sAfJ9o+ECc8YS\nWt2444x7XiRTMgFXsQ2H1LIej5qEnYZB0H+xr3ayCQGsG6hKsRiwjFcsJDTq\nMDmKFxIzbobdf3iBlIP+sQRg6Pek6RKreTyDBvNaG1JfsY0Ajz4Sw9Y+NEiw\nWUYKX1nbnt12MuRDPp9Efiv3e5F9BtSY1Or+wxXUNWDRoUmsEo3rC7tzy/er\nUPgoUtRAFk1D7df5Emj2fYqByhwy7I0KAQ4rBV841nACshPCSm2ibMIjCV9p\njgOT7s8sOr3gv8j4UWKdoCNIy61zfeSw8Cu1pOQwoDz8pWj2L1Xv6tdKHjso\nylfX\r\n=Ir1l\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBI1kym3a4TLRYXKwQ/QExkkCgMzKFHw54PCN4e+hzX3AiEAyXfb6HsHtKgbgeNpfjs8Lns1yJ7AiKaZQR+YJrS+71Q="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"yahgwai","email":"cpbuckland88@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.13-13_1590686121777_0.7108128110852534"},"_hasShrinkwrap":false},"0.0.13-14":{"name":"@anydotcrypto/metatransactions","version":"0.0.13-14","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deployScript.ts","generateSeed":"ts-node example/generateSeed.ts","echo-example":"ts-node example/proxyaccount/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build"},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single RelayHub contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nOur meta-transaction library focuses on both approaches and we hope it benefits the community in the following way:\n\n- **A candidate RelayHub standard**: Our RelayHub.sol is a minimal and potential candidate for the \\_msgSender() standard.\n- **Minimal proxy contracts**: Our proxy contract is only responsible for forwarding and batching calls. It implements EIP-1167 to minimise storage/deployment overhead.\n- **Flexible replay protection:** We have implemented Nonce, MultiNonce and BitFlip, so you can decide if all transactions must be ordered, if you want up to N concurrent transactions, or to always support out-of-order transactions.\n\nOur repository is a protocol and relay-independent approach that any project can adopt. We hope it will make it easier for projects to tap into third party relayer APIs and to avoid re-implementing the wheel for reliable transaction infrastructure.\n\n# Getting started\n\nWe assume you have set up your nodejs environment and you simply need to plug-in our library.\n\n1. **Install**. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. **Environment**. Decide which network and replay protection to use.\n\nYou will need to import both the ChainID and Replay Protection into your code:\n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\n\nOur library currently supports MAINNET or ROPSTEN.\n\n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\n\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n\n```\n// ReplayProtection\nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\n\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. **msg.sender solution**. Decide which solution to msg.sender you want to use.\n\nWhile we support both the RelayHub and the ProxyContract in this library, we recommend the proxy account contract approach for most purposes as it works for all existing smart contracts.\n\nIf you want to learn more, check out [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub).\n\nFor the rest of the documentation, we only consider the proxy contract approach.\n\n4. **Instantiate**. Let's create the meta-transaction library with your preferred options!\n\nTo instantiate the proxy account forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract.\n\nImportant: Our library can authorise a meta-transaction if the proxy account contract does not yet exist (e.g. not deployed). Using the [MultiSend](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/ops/MultiSend.sol) contract, it is possible to meta-deploy the proxy contract and then execute the first meta-transaction in a single Ethereum Transaction. So there is no waiting/setup process.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nThe [Echo smart contract](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/ops/Echo.sol) is used for our example:\n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## How to use the Proxy Account contract\n\nThe [full example](https://github.com/anydotcrypto/metatransactions/blob/master/example/proxyaccount/echo.ts) is available and it covers:\n\n- Checking the proxy contract exists before deploying it.\n- Deploying the Echo Contract via the proxy contract\n- Sending a meta-transaction to the Echo Contract via the proxy contract.\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the proxy account contract.\n\n```\nconst isProxyDeployed = await forwarder.isContractDeployed();\nif (!isProxyDeployed) {\n    const minimalTx = await forwarder.createProxyContract();\n\n    // For our example we mimic the relayer API with a relayer wallet.\n    const proxyTx = await relayer.sendTransaction({\n      to: minimalTx.to,\n      data: minimalTx.data,\n    });\n\n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nYou must supply the following information:\n\n- **Target** contract's address,\n- **Value** to be sent (in wei)\n- **Data** the function name and its arguments\n\nOnce you have settled on the message to echo, you can use this code sample to authorise the meta-transaction:\n\n```\n// Fetch the contract and the data.\nconst echo = new EchoFactory(user).attach(\"\");\nconst data = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signAndEncodeMetaTransaction({\n    target: echo.address,\n    value: \"0\",\n    data: data,\n});\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTx.data,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Our library has taken care of the replay protection & constructing the transaction data for you.\n\nWell done!\n\n# Proxy Account Contract Functionality\n\nWe take this opportunity to cover each function in the library.\n\n## Instantiate the forwarder\n\nYou can use the factory to set up a new forwarder. It requires you to select the ChainID and the ReplayProtectionType. Note if you select MULTINONCE, then it generates 30 nonce queues by default. (e.g. up to 30 concurrent transactions at any single time).\n\n```\n  const proxyAccount = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.BITFLIP,\n    user\n  );\n```\n\n## Properties\n\nOnce you have instantiated the forwarder, then you can access the following properties:\n\n```\nconst proxyAccountAddress = proxyAccount.address;\nconst signer = proxyAccount.signer;\n```\n\nThanks to the ProxyDeployer, there is a one-to-one mapping for a signer's key and the proxy account contract address. The library will automatically compute the address and make it available via `proxyAccount.address`. Furthermore, the `Signer` is accessible via `proxyAccount.signer`.\n\n## Deploying the Proxy Contract\n\nThere are two helper functions:\n\n```\nconst isProxyDeployed = await proxyAccount.isContractDeployed();\nconst minimalTx = await proxyAccount.createProxyContract();\n```\n\nThe former lets you check if the proxy contract is already deployed. The latter prepares a meta-transaction that can be packed into an Ethereum Transaction to deploy the proxy contract. Note the `MinimalTx` only contains the fields `to,data,value`.\n\n## Authorising a meta-transaction.\n\nThere is a single function for authorising a meta-transaction:\n\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signAndEncodeMetaTransaction({\n  target: echoAddress,\n  data: data,\n  value: \"0:\"\n});\n```\n\nIt returns a `MinimalTx` that only contains the fields `to, data, value` which can be packed into an Ethereum Transaction. This takes care of preparing the replay protection & wrapping the call so it can be processed by the proxy account contract.\n\nNote there is an additional `callType` field that can be used to decide if it is a `call` or a `delegatecall`. We only discuss call and advanced users can look at the contract on how to use delegatecall.\n\n## Authorising a meta-deployment.\n\nThere are two functions associated with meta-deployments:\n\n```\nconst initCode = new EchoFactory(user).getDeployTransaction().data! as string;\nconst value = \"0\";\nconst salt = \"0x123\";\nconst metaDeploy = await proxyAccount.signAndEncodeMetaDeployment(\n  initCode,\n  value,\n  salt\n);\n\nconst echoAddress = proxyAccount.buildDeployedContractAddress(\n  initCode,\n  salt\n);\n```\n\nThe `signAndEncodeMetaDeployment` function prepares a `MinimalTx` for the deployment. Again it only contains a `to,value,data` that can be packed in the Ethereum Transaction. In reality, it is using `delegatecall` from the proxy contract into a global deployer contract and then deploy the smart contract.\n\nThe `buildDeployedContractAddress` computes the address for the contract. It just requires the `initCode` and the `salt` used for the deployment.\n\n## Send a batch of meta-transactions\n\nYou need to prepare a list of transactions to use in the batch:\n\n```\nconst metaTxList = [{\n  target: msgSenderCon.address,\n  value: 0,\n  data: data,\n  revertOnFail: true,\n},\n{\n  target: echoCon.address,\n  value: 0,\n  data: data,\n  reverrtOnFail: false,\n}];\n```\n\nAn additional feature is `revertOnFail` which lets you decide if the entire batch of transactions should revert if the meta-transaction fails. Again, we omit `CallType` as it should only be used by advanced users and 99% of meta-transactions only require the `.call` functionality.\n\nNow you can batch the transactions:\n\n```\nconst minimalTx = await forwarder.signAndEncodeBatchTransaction(metaTxList);\n```\n\nThe `MinimalTx` contains the fields `to,data,value` that can be packed into an Ethereum Transaction. Each meta-transaction is processed in order by the proxy account contract.\n","readmeFilename":"README.md","gitHead":"7e194d901f812cfc903fdc7cad1efd608b8c389b","_id":"@anydotcrypto/metatransactions@0.0.13-14","_nodeVersion":"11.14.0","_npmVersion":"6.14.5","dist":{"integrity":"sha512-ARCXZzYd5fpA87pS2/u+4Hhdpsz49A4Ot1EJfKjbpLeoOyGs32W7JhqNUX4hor6C17P9G+5S8tyKQpD1NVlFRA==","shasum":"6470effb2e6eb630f3eb6088bd9995260992e8b9","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.13-14.tgz","fileCount":157,"unpackedSize":830749,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe13SrCRA9TVsSAnZWagAAKBYP/jzpURFE3fidSQmgtLg9\n4FyoFuTUsvk6gdgE/cqXr374GKqs7kDU5j7mRB/L9BX8UO3NEEDFb0V3GARD\na37NR7XttgyBoGZKX8/TuNsTyx6l/cGupzoHfVhRV8TZcfRrFgwFc7ul4L6c\nzTuEx1lbjQTNN64a988UxXjs327R8a/t2fp1a2oCn9hruKYuj2qtgWoksVzK\nC6rtsV/bHho6pq+Ryf9ixHuRxHj+MV48SNyYbgd0/1sc5DQ9hlCc+PIIHXxw\nrSgv4ZCVVfpgXEyVq3HLpm6m2wUodm5+OplnUKHDwlOeAD9seX9pZ78R4QcB\nOKZeGEgrr2VcLvCoI6tC5x6SYLJHUUw/NCUhkXKgOPqxX9tQedbudQLLukYo\nOZcfoZMQnsB9Qi6ILVW/yk6xjpHXY+9Qj9HHQ0oNce+fzTM3PBknQrjxGPyu\n8pIT4TuodPik9PRnDs8LDWyhHd73dfLODyj9og4hWY8FCESFW7yAV7TcFl3x\nLoV1UAgu78iAaX/vlV/6RWJ6UhqgFJfYWyPHCz/3obgRr9IjCszFY98POO7U\ng25gMMSzVG/0fwIwI9Xn6TZNBnOhYuqV1vMDq3i7PtwH8Mvf1OevHV96ijF1\nT7JfS1EhkVhVTnpxL9rQW4o+e8tA6WKdnT2K9EQ0VPE3GVXlXcqW/qBqd6TU\n1MI7\r\n=0w9w\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAY4ZffQFQsbfQrMVW2GyloXsXet3aMTUKXIbdubuGmAAiBaI/59P+ys3Cw323h22X58vvgXZ5qr0wYUAZw+pcK5RA=="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"yahgwai","email":"cpbuckland88@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.13-14_1591178411066_0.04429628289262344"},"_hasShrinkwrap":false},"0.0.13-15":{"name":"@anydotcrypto/metatransactions","version":"0.0.13-15","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deployScript.ts","generateSeed":"ts-node example/generateSeed.ts","echo-example":"ts-node example/proxyaccount/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build"},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single RelayHub contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nOur meta-transaction library focuses on both approaches and we hope it benefits the community in the following way:\n\n- **A candidate RelayHub standard**: Our RelayHub.sol is a minimal and potential candidate for the \\_msgSender() standard.\n- **Minimal proxy contracts**: Our proxy contract is only responsible for forwarding and batching calls. It implements EIP-1167 to minimise storage/deployment overhead.\n- **Flexible replay protection:** We have implemented Nonce, MultiNonce and BitFlip, so you can decide if all transactions must be ordered, if you want up to N concurrent transactions, or to always support out-of-order transactions.\n\nOur repository is a protocol and relay-independent approach that any project can adopt. We hope it will make it easier for projects to tap into third party relayer APIs and to avoid re-implementing the wheel for reliable transaction infrastructure.\n\n# Getting started\n\nWe assume you have set up your nodejs environment and you simply need to plug-in our library.\n\n1. **Install**. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. **Environment**. Decide which network and replay protection to use.\n\nYou will need to import both the ChainID and Replay Protection into your code:\n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\n\nOur library currently supports MAINNET or ROPSTEN.\n\n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\n\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n\n```\n// ReplayProtection\nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\n\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. **msg.sender solution**. Decide which solution to msg.sender you want to use.\n\nWhile we support both the RelayHub and the ProxyContract in this library, we recommend the proxy account contract approach for most purposes as it works for all existing smart contracts.\n\nIf you want to learn more, check out [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub).\n\nFor the rest of the documentation, we only consider the proxy contract approach.\n\n4. **Instantiate**. Let's create the meta-transaction library with your preferred options!\n\nTo instantiate the proxy account forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract.\n\nImportant: Our library can authorise a meta-transaction if the proxy account contract does not yet exist (e.g. not deployed). Using the [MultiSend](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/ops/MultiSend.sol) contract, it is possible to meta-deploy the proxy contract and then execute the first meta-transaction in a single Ethereum Transaction. So there is no waiting/setup process.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nThe [Echo smart contract](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/ops/Echo.sol) is used for our example:\n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## How to use the Proxy Account contract\n\nThe [full example](https://github.com/anydotcrypto/metatransactions/blob/master/example/proxyaccount/echo.ts) is available and it covers:\n\n- Checking the proxy contract exists before deploying it.\n- Deploying the Echo Contract via the proxy contract\n- Sending a meta-transaction to the Echo Contract via the proxy contract.\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the proxy account contract.\n\n```\nconst isProxyDeployed = await forwarder.isContractDeployed();\nif (!isProxyDeployed) {\n    const minimalTx = await forwarder.createProxyContract();\n\n    // For our example we mimic the relayer API with a relayer wallet.\n    const proxyTx = await relayer.sendTransaction({\n      to: minimalTx.to,\n      data: minimalTx.data,\n    });\n\n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nYou must supply the following information:\n\n- **Target** contract's address,\n- **Value** to be sent (in wei)\n- **Data** the function name and its arguments\n\nOnce you have settled on the message to echo, you can use this code sample to authorise the meta-transaction:\n\n```\n// Fetch the contract and the data.\nconst echo = new EchoFactory(user).attach(\"\");\nconst data = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signAndEncodeMetaTransaction({\n    target: echo.address,\n    value: \"0\",\n    data: data,\n});\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTx.data,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Our library has taken care of the replay protection & constructing the transaction data for you.\n\nWell done!\n\n# Proxy Account Contract Functionality\n\nWe take this opportunity to cover each function in the library.\n\n## Instantiate the forwarder\n\nYou can use the factory to set up a new forwarder. It requires you to select the ChainID and the ReplayProtectionType. Note if you select MULTINONCE, then it generates 30 nonce queues by default. (e.g. up to 30 concurrent transactions at any single time).\n\n```\n  const proxyAccount = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.BITFLIP,\n    user\n  );\n```\n\n## Properties\n\nOnce you have instantiated the forwarder, then you can access the following properties:\n\n```\nconst proxyAccountAddress = proxyAccount.address;\nconst signer = proxyAccount.signer;\n```\n\nThanks to the ProxyDeployer, there is a one-to-one mapping for a signer's key and the proxy account contract address. The library will automatically compute the address and make it available via `proxyAccount.address`. Furthermore, the `Signer` is accessible via `proxyAccount.signer`.\n\n## Deploying the Proxy Contract\n\nThere are two helper functions:\n\n```\nconst isProxyDeployed = await proxyAccount.isContractDeployed();\nconst minimalTx = await proxyAccount.createProxyContract();\n```\n\nThe former lets you check if the proxy contract is already deployed. The latter prepares a meta-transaction that can be packed into an Ethereum Transaction to deploy the proxy contract. Note the `MinimalTx` only contains the fields `to,data,value`.\n\n## Authorising a meta-transaction.\n\nThere is a single function for authorising a meta-transaction:\n\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signAndEncodeMetaTransaction({\n  target: echoAddress,\n  data: data,\n  value: \"0:\"\n});\n```\n\nIt returns a `MinimalTx` that only contains the fields `to, data, value` which can be packed into an Ethereum Transaction. This takes care of preparing the replay protection & wrapping the call so it can be processed by the proxy account contract.\n\nNote there is an additional `callType` field that can be used to decide if it is a `call` or a `delegatecall`. We only discuss call and advanced users can look at the contract on how to use delegatecall.\n\n## Authorising a meta-deployment.\n\nThere are two functions associated with meta-deployments:\n\n```\nconst initCode = new EchoFactory(user).getDeployTransaction().data! as string;\nconst value = \"0\";\nconst salt = \"0x123\";\nconst metaDeploy = await proxyAccount.signAndEncodeMetaDeployment(\n  initCode,\n  value,\n  salt\n);\n\nconst echoAddress = proxyAccount.buildDeployedContractAddress(\n  initCode,\n  salt\n);\n```\n\nThe `signAndEncodeMetaDeployment` function prepares a `MinimalTx` for the deployment. Again it only contains a `to,value,data` that can be packed in the Ethereum Transaction. In reality, it is using `delegatecall` from the proxy contract into a global deployer contract and then deploy the smart contract.\n\nThe `buildDeployedContractAddress` computes the address for the contract. It just requires the `initCode` and the `salt` used for the deployment.\n\n## Send a batch of meta-transactions\n\nYou need to prepare a list of transactions to use in the batch:\n\n```\nconst metaTxList = [{\n  target: msgSenderCon.address,\n  value: 0,\n  data: data,\n  revertOnFail: true,\n},\n{\n  target: echoCon.address,\n  value: 0,\n  data: data,\n  reverrtOnFail: false,\n}];\n```\n\nAn additional feature is `revertOnFail` which lets you decide if the entire batch of transactions should revert if the meta-transaction fails. Again, we omit `CallType` as it should only be used by advanced users and 99% of meta-transactions only require the `.call` functionality.\n\nNow you can batch the transactions:\n\n```\nconst minimalTx = await forwarder.signAndEncodeBatchTransaction(metaTxList);\n```\n\nThe `MinimalTx` contains the fields `to,data,value` that can be packed into an Ethereum Transaction. Each meta-transaction is processed in order by the proxy account contract.\n","readmeFilename":"README.md","gitHead":"635e99790ca2466da9e13d3b5a9b735674f2b773","_id":"@anydotcrypto/metatransactions@0.0.13-15","_nodeVersion":"11.14.0","_npmVersion":"6.14.5","dist":{"integrity":"sha512-IEcMZKEScfU2JI/OY4ilDoKNS1D1R8AOrOLFlswbuy/zV3ePa1PbgzU8MkbaUjbUArO1mz7VVt7e+V8RgW5aOg==","shasum":"034bcc9395b5b1d805bfe5f3596a38a8f30c4b97","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.13-15.tgz","fileCount":157,"unpackedSize":830884,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe14B3CRA9TVsSAnZWagAAr4IP/jplBrszzXZ2XyuBAkPg\n7TN+rWaTSUpifuBjInEWoqyv0OxeDCiT3ka95e45kOQ8ByxRlmtlRFtW5N6z\n/9xW0YQXhJQzK8VvzlOONTR7FOz1i4JeGVy4wsEaLs+h0CQ0+okpJC502VTq\n7CX3/pTNoj3qy5FR53w/RmxPebcg/AVn730pmyAkkkvJqQNz0In+QnFdKwyV\nJNHegIi8OyfzbKc7U1BzZByxBvzk7p1GQZzrbDaB5lLhsoPfZNnSqz4LWJOB\nnnwu32+ubdLpgWACEzIpHVnhV15wOoUryTXoM6npVgsl2eQzVS1frf047dbr\nohZS+PZkdpz1v1kmJDbYOauV+P/wsDd3tzf2U/BNI43rWSoXf4d+/gxy1ePS\n9D02D0U1YuzafrUDofweYzZVHL5QPk7V26tTaRec8Y7CJFQBC84FZlPBMa1J\nQFay9p9j30H97V6iHyvqDCr2pmcxSd9ZyhWOcGpWEuDHKSKPfpl6LBWcxVmE\nwOX0JghVNkhtrvl7IEW7MmKtFlLmfU/YmwdgPP8BRtQfr0fUJEPKt03eTkR3\nRlLJCOhNlWYES19XVR41PWLfBqBL4I9Or+fYeDDyU9hS1HACOQRheq28y8ef\ngV3qQR+JraW3n4Yl9ds9wuXMNzELMGfNHh9S5J8lGcsqsVm/mvO09fV/wcjB\nabTw\r\n=VAP4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIH1279H7J8jN5xg+abBUkLEIFkDBiHrdeJZOZ0xtUarzAiEAxA4OmpJFH6cXrlL7f9MZ6XKbpdFJ96CHj6PraHYmDV0="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"yahgwai","email":"cpbuckland88@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.13-15_1591181431181_0.14053864426213059"},"_hasShrinkwrap":false},"0.0.13":{"name":"@anydotcrypto/metatransactions","version":"0.0.13","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deployScript.ts","generateSeed":"ts-node example/generateSeed.ts","echo-example":"ts-node example/proxyaccount/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build"},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single RelayHub contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nOur meta-transaction library focuses on both approaches and we hope it benefits the community in the following way:\n\n- **A candidate RelayHub standard**: Our RelayHub.sol is a minimal and potential candidate for the \\_msgSender() standard.\n- **Minimal proxy contracts**: Our proxy contract is only responsible for forwarding and batching calls. It implements EIP-1167 to minimise storage/deployment overhead.\n- **Flexible replay protection:** We have implemented Nonce, MultiNonce and BitFlip, so you can decide if all transactions must be ordered, if you want up to N concurrent transactions, or to always support out-of-order transactions.\n\nOur repository is a protocol and relay-independent approach that any project can adopt. We hope it will make it easier for projects to tap into third party relayer APIs and to avoid re-implementing the wheel for reliable transaction infrastructure.\n\n# Getting started\n\nWe assume you have set up your nodejs environment and you simply need to plug-in our library.\n\n1. **Install**. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. **Environment**. Decide which network and replay protection to use.\n\nYou will need to import both the ChainID and Replay Protection into your code:\n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\n\nOur library currently supports MAINNET or ROPSTEN.\n\n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\n\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n\n```\n// ReplayProtection\nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\n\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. **msg.sender solution**. Decide which solution to msg.sender you want to use.\n\nWhile we support both the RelayHub and the ProxyContract in this library, we recommend the proxy account contract approach for most purposes as it works for all existing smart contracts.\n\nIf you want to learn more, check out [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub).\n\nFor the rest of the documentation, we only consider the proxy contract approach.\n\n4. **Instantiate**. Let's create the meta-transaction library with your preferred options!\n\nTo instantiate the proxy account forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract.\n\nImportant: Our library can authorise a meta-transaction if the proxy account contract does not yet exist (e.g. not deployed). Using the [MultiSend](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/ops/MultiSend.sol) contract, it is possible to meta-deploy the proxy contract and then execute the first meta-transaction in a single Ethereum Transaction. So there is no waiting/setup process.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nThe [Echo smart contract](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/ops/Echo.sol) is used for our example:\n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## How to use the Proxy Account contract\n\nThe [full example](https://github.com/anydotcrypto/metatransactions/blob/master/example/proxyaccount/echo.ts) is available and it covers:\n\n- Checking the proxy contract exists before deploying it.\n- Deploying the Echo Contract via the proxy contract\n- Sending a meta-transaction to the Echo Contract via the proxy contract.\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the proxy account contract.\n\n```\nconst isProxyDeployed = await forwarder.isContractDeployed();\nif (!isProxyDeployed) {\n    const minimalTx = await forwarder.createProxyContract();\n\n    // For our example we mimic the relayer API with a relayer wallet.\n    const proxyTx = await relayer.sendTransaction({\n      to: minimalTx.to,\n      data: minimalTx.data,\n    });\n\n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nYou must supply the following information:\n\n- **Target** contract's address,\n- **Value** to be sent (in wei)\n- **Data** the function name and its arguments\n\nOnce you have settled on the message to echo, you can use this code sample to authorise the meta-transaction:\n\n```\n// Fetch the contract and the data.\nconst echo = new EchoFactory(user).attach(\"\");\nconst data = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signAndEncodeMetaTransaction({\n    target: echo.address,\n    value: \"0\",\n    data: data,\n});\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTx.data,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Our library has taken care of the replay protection & constructing the transaction data for you.\n\nWell done!\n\n# Proxy Account Contract Functionality\n\nWe take this opportunity to cover each function in the library.\n\n## Instantiate the forwarder\n\nYou can use the factory to set up a new forwarder. It requires you to select the ChainID and the ReplayProtectionType. Note if you select MULTINONCE, then it generates 30 nonce queues by default. (e.g. up to 30 concurrent transactions at any single time).\n\n```\n  const proxyAccount = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.BITFLIP,\n    user\n  );\n```\n\n## Properties\n\nOnce you have instantiated the forwarder, then you can access the following properties:\n\n```\nconst proxyAccountAddress = proxyAccount.address;\nconst signer = proxyAccount.signer;\n```\n\nThanks to the ProxyDeployer, there is a one-to-one mapping for a signer's key and the proxy account contract address. The library will automatically compute the address and make it available via `proxyAccount.address`. Furthermore, the `Signer` is accessible via `proxyAccount.signer`.\n\n## Deploying the Proxy Contract\n\nThere are two helper functions:\n\n```\nconst isProxyDeployed = await proxyAccount.isContractDeployed();\nconst minimalTx = await proxyAccount.createProxyContract();\n```\n\nThe former lets you check if the proxy contract is already deployed. The latter prepares a meta-transaction that can be packed into an Ethereum Transaction to deploy the proxy contract. Note the `MinimalTx` only contains the fields `to,data,value`.\n\n## Authorising a meta-transaction.\n\nThere is a single function for authorising a meta-transaction:\n\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signAndEncodeMetaTransaction({\n  target: echoAddress,\n  data: data,\n  value: \"0:\"\n});\n```\n\nIt returns a `MinimalTx` that only contains the fields `to, data, value` which can be packed into an Ethereum Transaction. This takes care of preparing the replay protection & wrapping the call so it can be processed by the proxy account contract.\n\nNote there is an additional `callType` field that can be used to decide if it is a `call` or a `delegatecall`. We only discuss call and advanced users can look at the contract on how to use delegatecall.\n\n## Authorising a meta-deployment.\n\nThere are two functions associated with meta-deployments:\n\n```\nconst initCode = new EchoFactory(user).getDeployTransaction().data! as string;\nconst value = \"0\";\nconst salt = \"0x123\";\nconst metaDeploy = await proxyAccount.signAndEncodeMetaDeployment(\n  initCode,\n  value,\n  salt\n);\n\nconst echoAddress = proxyAccount.buildDeployedContractAddress(\n  initCode,\n  salt\n);\n```\n\nThe `signAndEncodeMetaDeployment` function prepares a `MinimalTx` for the deployment. Again it only contains a `to,value,data` that can be packed in the Ethereum Transaction. In reality, it is using `delegatecall` from the proxy contract into a global deployer contract and then deploy the smart contract.\n\nThe `buildDeployedContractAddress` computes the address for the contract. It just requires the `initCode` and the `salt` used for the deployment.\n\n## Send a batch of meta-transactions\n\nYou need to prepare a list of transactions to use in the batch:\n\n```\nconst metaTxList = [{\n  target: msgSenderCon.address,\n  value: 0,\n  data: data,\n  revertOnFail: true,\n},\n{\n  target: echoCon.address,\n  value: 0,\n  data: data,\n  reverrtOnFail: false,\n}];\n```\n\nAn additional feature is `revertOnFail` which lets you decide if the entire batch of transactions should revert if the meta-transaction fails. Again, we omit `CallType` as it should only be used by advanced users and 99% of meta-transactions only require the `.call` functionality.\n\nNow you can batch the transactions:\n\n```\nconst minimalTx = await forwarder.signAndEncodeBatchTransaction(metaTxList);\n```\n\nThe `MinimalTx` contains the fields `to,data,value` that can be packed into an Ethereum Transaction. Each meta-transaction is processed in order by the proxy account contract.\n","readmeFilename":"README.md","gitHead":"dae5286495839f12f71efcb3260c8e792c1592a2","_id":"@anydotcrypto/metatransactions@0.0.13","_nodeVersion":"11.10.1","_npmVersion":"6.14.5","dist":{"integrity":"sha512-aJjoLCekaYVo0HPodMqSdLyJOkFhIX5c/D4NkL+88GjuZPZYwgCoETHWNVl8nylqqLPqP6+OA7Q3rbH3AWWuxQ==","shasum":"e41ba5625cedcd3f0470fca54de54673a35a17cd","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.13.tgz","fileCount":169,"unpackedSize":855387,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe4OKXCRA9TVsSAnZWagAANcEQAImoZN6o9yhF3zl9IDxV\n1JJFvX4NdQVv22L1FWLE0GKEb8JeMgn3L22+2qXP3rfCEFaOkGhmB/1H1dDD\nqe54WkQr6b2QRDOu9vE0IntqcA2AlHL+CAe9a7dbE66UByqHG9/9PNly+l2A\n26tueJcEL8Kl7EXmwBcYsaID1Ygh7k9llAG1ZqTxwYO4isqjvNQLTDsDO+b1\nS/71lgSOir8InLVyrdz38dUmyWu41Mdo99lKB5LTdpdugr/QhCPGNk91QHpo\nnv43EfRpnxrf3jTjQonSc/XdBqsVSLXS4j9CUO+8yijVkyFkKX0ox1xO838X\nyroKtgNFpe44gj8c5I6/4Jg5U96ULEqfmY0pTxzo5iG2NQkON9RO6ER4mQx6\nIchUn+3isOztNIigwInrHh48KSgNdyjaVpmABMVxYP/un0+LFN+5C9eXMKl+\nUk0LHg97FnIl9AKpuPUglSxg6BohFGk5IBP7DMqrUfZ6RMYqrHi4eG8hO34D\nMEw9d3gVAZvbzB3ptmSFTskw/1lNwQwoSFckU8uWDAPKtoa+s3C5qygbR1mh\nRWYCS2mxCHxfEjsKuwuqME1ZeG4dJV1M2EF+KUu97CiyT6JPwHiky4/UfbK6\nHxAfYay/2qTEds763AAdJ6j0I9/9Kwnceu+lkmjRwhx+nLLS40HDrrZ4y1xG\n+c9B\r\n=xocf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBojf04EwTOPvIf1yjm8DZsrXMFqo6HCmvJ4scqs39QsAiEA2T3Gy7wNCPB7KXEUhYVYedL0VrUGB3tGXgnzZ7kLZ3I="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.13_1591796375239_0.5067215700737324"},"_hasShrinkwrap":false},"0.0.14":{"name":"@anydotcrypto/metatransactions","version":"0.0.14","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deployScript.ts","generateSeed":"ts-node example/generateSeed.ts","echo-example":"ts-node example/proxyaccount/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build"},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"gitHead":"69e5676124e87f5d7be6d907a19d10890cd155d6","_id":"@anydotcrypto/metatransactions@0.0.14","_nodeVersion":"11.14.0","_npmVersion":"6.14.5","dist":{"integrity":"sha512-wq7hu5v68mqvDI6uUS3Wh2Auq1vJEVBizx81cbUTtk8lZ9ENJnKqDWrwB3yDtrAvcr6CxHY4+zeuaY8fz9y1hw==","shasum":"00318a9c06839e36ab3883e19bcaf7120dc2d532","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.14.tgz","fileCount":157,"unpackedSize":823022,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe6jODCRA9TVsSAnZWagAAMtkP/R/GRKHSPzHJ4mRhc503\n5tHjEPMe4/VQvFQAfFl90TQBZZBLmh3DtSM4O/hxkWvdTyMC3n1mGPZIBVcP\nAWfFpiDnAZs//1nQbkFADLV8wBQdVRoOorR3pIaQ9Fm+QFtPygpFKx+rhb4R\n9RJGxyjnDjA8rdFHNYeKG8/tSDGWffGbXca+iHyFauPxO5PejMtVoOe1vOdV\n1dgjEf5bGLzbWk6Pen1SNl8S2AemFWsK0QWNX/K0i50WzinRQjiWboKNahVD\n4XF+MUwzgvzYXokJ1MKCtvhGBGZ7ohqUElYTeK4TmqgrSCH+qDOYQfueWKu3\neOJKbTcerpc0Thy2HzDoayuIoW5OchmpXsfx+RkV2sJftDSYYTvA7xV62AmM\n5eP5xVqMWK+Sl2rWafX95qSg3pdfo1OjWIvLoi0igGvL1qHSpzcHFl6W+2ZM\nRbYmo3/8JMKIIRUqczKBmYQZLZM42mbHjQn1l1sq2xRBo3Er543Aa9ckALhF\nLhjWl8n6d5ZITkaJfl8IAIrZZ13HYxmOdBbAE7Y4l/5yJjCV4hn7KN2zdDm5\nubevwBXNrtwQ9f8SvjyV9KuRX6qQJVZUuumvD7OSXEuf8qQlDhnXoNyj09Dw\n3jpzj4qsqQACySG5Uqu+oCFO4+1eHt2u3ICcoHpov+eijGjMIpG/qqhVra61\nCUdq\r\n=7e8C\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD0bEbN+9EJWtCIVjlSNNEELtNODATy1zZYBS7Cxx6BpAIgbBIJT5jzE9j288VlAyLD/SQYxGY9ke7DmRk3m0+k0Jw="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"yahgwai","email":"cpbuckland88@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.14_1592406915097_0.8242742874568152"},"_hasShrinkwrap":false},"0.0.15-0":{"name":"@anydotcrypto/metatransactions","version":"0.0.15-0","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-gnosis && npm run build-types","build-gnosis":"waffle waffle053.json","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deployScript.ts","generateSeed":"ts-node example/generateSeed.ts","echo-example":"ts-node example/proxyaccount/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build"},"devDependencies":{"@gnosis.pm/mock-contract":"^3.0.8","@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single RelayHub contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nOur meta-transaction library focuses on both approaches and we hope it benefits the community in the following way:\n\n- **A candidate RelayHub standard**: Our RelayHub.sol is a minimal and potential candidate for the \\_msgSender() standard.\n- **Minimal proxy contracts**: Our proxy contract is only responsible for forwarding and batching calls. It implements EIP-1167 to minimise storage/deployment overhead.\n- **Flexible replay protection:** We have implemented Nonce, MultiNonce and BitFlip, so you can decide if all transactions must be ordered, if you want up to N concurrent transactions, or to always support out-of-order transactions.\n\nOur repository is a protocol and relay-independent approach that any project can adopt. We hope it will make it easier for projects to tap into third party relayer APIs and to avoid re-implementing the wheel for reliable transaction infrastructure.\n\n# Getting started\n\nWe assume you have set up your nodejs environment and you simply need to plug-in our library.\n\n1. **Install**. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. **Environment**. Decide which network and replay protection to use.\n\nYou will need to import both the ChainID and Replay Protection into your code:\n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\n\nOur library currently supports MAINNET or ROPSTEN.\n\n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\n\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n\n```\n// ReplayProtection\nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\n\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. **msg.sender solution**. Decide which solution to msg.sender you want to use.\n\nWhile we support both the RelayHub and the ProxyContract in this library, we recommend the proxy account contract approach for most purposes as it works for all existing smart contracts.\n\nIf you want to learn more, check out [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub).\n\nFor the rest of the documentation, we only consider the proxy contract approach.\n\n4. **Instantiate**. Let's create the meta-transaction library with your preferred options!\n\nTo instantiate the proxy account forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract.\n\nImportant: Our library can authorise a meta-transaction if the proxy account contract does not yet exist (e.g. not deployed). Using the [MultiSend](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/ops/MultiSend.sol) contract, it is possible to meta-deploy the proxy contract and then execute the first meta-transaction in a single Ethereum Transaction. So there is no waiting/setup process.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nThe [Echo smart contract](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/ops/Echo.sol) is used for our example:\n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## How to use the Proxy Account contract\n\nThe [full example](https://github.com/anydotcrypto/metatransactions/blob/master/example/proxyaccount/echo.ts) is available and it covers:\n\n- Checking the proxy contract exists before deploying it.\n- Deploying the Echo Contract via the proxy contract\n- Sending a meta-transaction to the Echo Contract via the proxy contract.\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the proxy account contract.\n\n```\nconst isProxyDeployed = await forwarder.isContractDeployed();\nif (!isProxyDeployed) {\n    const minimalTx = await forwarder.createProxyContract();\n\n    // For our example we mimic the relayer API with a relayer wallet.\n    const proxyTx = await relayer.sendTransaction({\n      to: minimalTx.to,\n      data: minimalTx.data,\n    });\n\n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nSupply the following information:\n\n- **To** contract's address (required)\n- **Data** the function name and its arguments (required)\n- **Value** to be sent (in wei) - (optional)\n\nOnce you have settled on the message to echo, you can use this code sample to authorise the meta-transaction:\n\n```\n// Fetch the contract and the data.\nconst echo = new EchoFactory(user).attach(\"\");\nconst data = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    to: echo.address,\n    value: \"0\",\n    data: data,\n});\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTx.data,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Our library has taken care of the replay protection & constructing the transaction data for you.\n\nWell done!\n\n# Proxy Account Contract Functionality\n\nWe take this opportunity to cover each function in the library.\n\n## Instantiate the forwarder\n\nYou can use the factory to set up a new forwarder. It requires you to select the ChainID and the ReplayProtectionType. Note if you select MULTINONCE, then it generates 30 nonce queues by default. (e.g. up to 30 concurrent transactions at any single time).\n\n```\n  const proxyAccount = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.BITFLIP,\n    user\n  );\n```\n\n## Properties\n\nOnce you have instantiated the forwarder, then you can access the following properties:\n\n```\nconst proxyAccountAddress = proxyAccount.address;\nconst signer = proxyAccount.signer;\n```\n\nThanks to the ProxyDeployer, there is a one-to-one mapping for a signer's key and the proxy account contract address. The library will automatically compute the address and make it available via `proxyAccount.address`. Furthermore, the `Signer` is accessible via `proxyAccount.signer`.\n\n## Deploying the Proxy Contract\n\nThere are two helper functions:\n\n```\nconst isProxyDeployed = await proxyAccount.isContractDeployed();\nconst minimalTx = await proxyAccount.createProxyContract();\n```\n\nThe former lets you check if the proxy contract is already deployed. The latter prepares a meta-transaction that can be packed into an Ethereum Transaction to deploy the proxy contract. Note the `MinimalTx` only contains the fields `to, data`.\n\n## Authorising a meta-transaction.\n\nThere is a single function for authorising a meta-transaction:\n\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction({\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n});\n```\n\nIt returns a `MinimalTx` that only contains the fields `to, data` which can be packed into an Ethereum Transaction. This takes care of preparing the replay protection & wrapping the call so it can be processed by the proxy account contract.\n\nNote there is an additional `callType` field that can be used to decide if it is a `call` or a `delegatecall`. We only discuss call and advanced users can look at the contract on how to use delegatecall.\n\n## Authorising a meta-deployment.\n\nTo deploy use the signMetaTransaction function but replace the `to` argument with a `salt`:\n\n```\nconst initCode = new EchoFactory(user).getDeployTransaction().data!;\nconst value = \"0\";\nconst salt = \"0x123\";\nconst metaDeploy = await proxyAccount.signMetaTransaction({\n  initCode,\n  value,\n  salt\n});\n```\n\nThe `signAndEncodeMetaDeployment` function prepares a `MinimalTx` for the deployment. Again it only contains a `to,value,data` that can be packed in the Ethereum Transaction. In reality, it is using `delegatecall` from the proxy contract into a global deployer contract and then deploy the smart contract.\n\nThe `buildDeployedContractAddress` computes the address for the contract. It just requires the `initCode` and the `salt` used for the deployment.\n\n## Send a batch of meta-transactions\n\nYou need to prepare a list of transactions to use in the batch:\n\n```\nconst metaTxList = [{\n  to: msgSenderCon.address,\n  value: 0,\n  data: data,\n  revertOnFail: true,\n},\n{\n  data: initCode,\n  salt: \"v0.1\",\n  value: 0\n},\n{\n  to: echoCon.address,\n  value: 0,\n  data: data,\n  revertOnFail: false,\n}];\n```\n\nAn additional feature is `revertOnFail` which lets you decide if the entire batch of transactions should revert if the meta-transaction fails. Again, we omit `CallType` as it should only be used by advanced users and 99% of meta-transactions only require the `.call` functionality.\n\nNow you can batch the transactions:\n```\nconst minimalTx = await forwarder.signMetaTransaction(metaTxList);\n```\n\nThe `MinimalTx` contains the fields `to, data` that can be packed into an Ethereum Transaction. Each meta-transaction is processed in order by the proxy account contract.\n\n## Decoding a metatransaction\n\nYou can decode a metatransaction into it's consutituent parts by using the decodeTx or decodeBatchTx functions.\n\nFor a single tx:\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction({\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n});\nconst forwardFunctionArguments = proxyAccount.decodeTx(metaTx.data);\n```\n\nOr for a batch tx:\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction([{\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n}]);\nconst forwardFunctionArguments = proxyAccount.decodeBatchTx(metaTx.data);\n```","readmeFilename":"README.md","gitHead":"fa5f7a525c5a6c7c26159c52665e5e771c37a57e","_id":"@anydotcrypto/metatransactions@0.0.15-0","_nodeVersion":"11.10.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-i4t8zI6CB4LfINRQLBDqtqwlGrnBNmJYxfidGxzzSFrEItbrXanaF5AB1UG7ObDIwl5T8xuq35ptOWVFusXxKA==","shasum":"fc907ff8c5cef2238dbe5d69f8cd3693a5f9cbfc","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.15-0.tgz","fileCount":314,"unpackedSize":2425650,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfGZHCCRA9TVsSAnZWagAAt6UQAInJNwb1Cd02LLeBrZK3\nVYShgkxLsZDyzGtdWsmv7y5PSd/7dYAeTQ1y9IgFj4pwoyN/ejzHejRPjpd9\nE5qFvGLOUTNalbFEBjg6cy6WFRewsnF4Li7BSuBbepWQN06KMNFTMeVRx0S+\ncoZc8SzPDcoqwhHWBZF70QNYN2ObRN9pCav8JAgMb4sItMP3EXp9CMXAwnp6\njr62ZCmqxP8FiDU0XwKxzqcK89mA8GyAkVlle16STV5mn6K1Ca6HQybkYWQj\nAY263U+P1pCVmFyBFgpaEksU9Cndt2Bzw1sQfMG/mcYOP8H7XuziI1fTVtmQ\n6nmijy+50YVRYXhYZJiS+hzuG22dNaGWUSuPzGu2WdDsHbVHDhBDqKnfD4NO\nwG5lRsAUFqgtM4nNFcOAxmICvVD4E9d3kKswpVySLoVBrsuESeqWzI58tqqd\n6LGac8Z7iwO2BR8wA1TGviqMaGxGTnaECEyoxbvITA1UY/nPcPZQk5VivSR9\nBiVoFJ7x0JmGdwvIisBmC6NUtwDxvCD6BrIyv39c+RxwTwJtQlR6k45SGf6f\n1kQ88u5WTmt8uTmspOlXTPA1Tzf+jjDl2OWX9OIA4EYNOSoz0HKNBFClaFIk\njx4p6SWY2Ye9PdmtNpYiX0Ire+ZlGhJoYMNTRbqWz/KdnmKc3AyoMOJEBN4W\neIVH\r\n=Q05R\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCkWSetmvQikrx33wawkDNS5Qo5a0Xw9oRZ9HpgclAKogIgY1sJSjqIoJzx8UqBohP5BBNrrHY9T3xHZJWTcNqBhlM="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.15-0_1595511233517_0.014069179162854217"},"_hasShrinkwrap":false},"0.0.15-1":{"name":"@anydotcrypto/metatransactions","version":"0.0.15-1","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-gnosis && npm run build-types","build-gnosis":"waffle waffle053.json","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deployScript.ts","generateSeed":"ts-node example/generateSeed.ts","echo-example":"ts-node example/proxyaccount/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build"},"devDependencies":{"@gnosis.pm/mock-contract":"^3.0.8","@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single RelayHub contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nOur meta-transaction library focuses on both approaches and we hope it benefits the community in the following way:\n\n- **A candidate RelayHub standard**: Our RelayHub.sol is a minimal and potential candidate for the \\_msgSender() standard.\n- **Minimal proxy contracts**: Our proxy contract is only responsible for forwarding and batching calls. It implements EIP-1167 to minimise storage/deployment overhead.\n- **Flexible replay protection:** We have implemented Nonce, MultiNonce and BitFlip, so you can decide if all transactions must be ordered, if you want up to N concurrent transactions, or to always support out-of-order transactions.\n\nOur repository is a protocol and relay-independent approach that any project can adopt. We hope it will make it easier for projects to tap into third party relayer APIs and to avoid re-implementing the wheel for reliable transaction infrastructure.\n\n# Getting started\n\nWe assume you have set up your nodejs environment and you simply need to plug-in our library.\n\n1. **Install**. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. **Environment**. Decide which network and replay protection to use.\n\nYou will need to import both the ChainID and Replay Protection into your code:\n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\n\nOur library currently supports MAINNET or ROPSTEN.\n\n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\n\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n\n```\n// ReplayProtection\nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\n\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. **msg.sender solution**. Decide which solution to msg.sender you want to use.\n\nWhile we support both the RelayHub and the ProxyContract in this library, we recommend the proxy account contract approach for most purposes as it works for all existing smart contracts.\n\nIf you want to learn more, check out [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub).\n\nFor the rest of the documentation, we only consider the proxy contract approach.\n\n4. **Instantiate**. Let's create the meta-transaction library with your preferred options!\n\nTo instantiate the proxy account forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract.\n\nImportant: Our library can authorise a meta-transaction if the proxy account contract does not yet exist (e.g. not deployed). Using the [MultiSend](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/ops/MultiSend.sol) contract, it is possible to meta-deploy the proxy contract and then execute the first meta-transaction in a single Ethereum Transaction. So there is no waiting/setup process.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nThe [Echo smart contract](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/ops/Echo.sol) is used for our example:\n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## How to use the Proxy Account contract\n\nThe [full example](https://github.com/anydotcrypto/metatransactions/blob/master/example/proxyaccount/echo.ts) is available and it covers:\n\n- Checking the proxy contract exists before deploying it.\n- Deploying the Echo Contract via the proxy contract\n- Sending a meta-transaction to the Echo Contract via the proxy contract.\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the proxy account contract.\n\n```\nconst isProxyDeployed = await forwarder.isContractDeployed();\nif (!isProxyDeployed) {\n    const minimalTx = await forwarder.createProxyContract();\n\n    // For our example we mimic the relayer API with a relayer wallet.\n    const proxyTx = await relayer.sendTransaction({\n      to: minimalTx.to,\n      data: minimalTx.data,\n    });\n\n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nSupply the following information:\n\n- **To** contract's address (required)\n- **Data** the function name and its arguments (required)\n- **Value** to be sent (in wei) - (optional)\n\nOnce you have settled on the message to echo, you can use this code sample to authorise the meta-transaction:\n\n```\n// Fetch the contract and the data.\nconst echo = new EchoFactory(user).attach(\"\");\nconst data = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    to: echo.address,\n    value: \"0\",\n    data: data,\n});\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTx.data,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Our library has taken care of the replay protection & constructing the transaction data for you.\n\nWell done!\n\n# Proxy Account Contract Functionality\n\nWe take this opportunity to cover each function in the library.\n\n## Instantiate the forwarder\n\nYou can use the factory to set up a new forwarder. It requires you to select the ChainID and the ReplayProtectionType. Note if you select MULTINONCE, then it generates 30 nonce queues by default. (e.g. up to 30 concurrent transactions at any single time).\n\n```\n  const proxyAccount = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.BITFLIP,\n    user\n  );\n```\n\n## Properties\n\nOnce you have instantiated the forwarder, then you can access the following properties:\n\n```\nconst proxyAccountAddress = proxyAccount.address;\nconst signer = proxyAccount.signer;\n```\n\nThanks to the ProxyDeployer, there is a one-to-one mapping for a signer's key and the proxy account contract address. The library will automatically compute the address and make it available via `proxyAccount.address`. Furthermore, the `Signer` is accessible via `proxyAccount.signer`.\n\n## Deploying the Proxy Contract\n\nThere are two helper functions:\n\n```\nconst isProxyDeployed = await proxyAccount.isContractDeployed();\nconst minimalTx = await proxyAccount.createProxyContract();\n```\n\nThe former lets you check if the proxy contract is already deployed. The latter prepares a meta-transaction that can be packed into an Ethereum Transaction to deploy the proxy contract. Note the `MinimalTx` only contains the fields `to, data`.\n\n## Authorising a meta-transaction.\n\nThere is a single function for authorising a meta-transaction:\n\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction({\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n});\n```\n\nIt returns a `MinimalTx` that only contains the fields `to, data` which can be packed into an Ethereum Transaction. This takes care of preparing the replay protection & wrapping the call so it can be processed by the proxy account contract.\n\nNote there is an additional `callType` field that can be used to decide if it is a `call` or a `delegatecall`. We only discuss call and advanced users can look at the contract on how to use delegatecall.\n\n## Authorising a meta-deployment.\n\nTo deploy use the signMetaTransaction function but replace the `to` argument with a `salt`:\n\n```\nconst initCode = new EchoFactory(user).getDeployTransaction().data!;\nconst value = \"0\";\nconst salt = \"0x123\";\nconst metaDeploy = await proxyAccount.signMetaTransaction({\n  initCode,\n  value,\n  salt\n});\n```\n\nThe `signAndEncodeMetaDeployment` function prepares a `MinimalTx` for the deployment. Again it only contains a `to,value,data` that can be packed in the Ethereum Transaction. In reality, it is using `delegatecall` from the proxy contract into a global deployer contract and then deploy the smart contract.\n\nThe `buildDeployedContractAddress` computes the address for the contract. It just requires the `initCode` and the `salt` used for the deployment.\n\n## Send a batch of meta-transactions\n\nYou need to prepare a list of transactions to use in the batch:\n\n```\nconst metaTxList = [{\n  to: msgSenderCon.address,\n  value: 0,\n  data: data,\n  revertOnFail: true,\n},\n{\n  data: initCode,\n  salt: \"v0.1\",\n  value: 0\n},\n{\n  to: echoCon.address,\n  value: 0,\n  data: data,\n  revertOnFail: false,\n}];\n```\n\nAn additional feature is `revertOnFail` which lets you decide if the entire batch of transactions should revert if the meta-transaction fails. Again, we omit `CallType` as it should only be used by advanced users and 99% of meta-transactions only require the `.call` functionality.\n\nNow you can batch the transactions:\n```\nconst minimalTx = await forwarder.signMetaTransaction(metaTxList);\n```\n\nThe `MinimalTx` contains the fields `to, data` that can be packed into an Ethereum Transaction. Each meta-transaction is processed in order by the proxy account contract.\n\n## Decoding a metatransaction\n\nYou can decode a metatransaction into it's consutituent parts by using the decodeTx or decodeBatchTx functions.\n\nFor a single tx:\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction({\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n});\nconst forwardFunctionArguments = proxyAccount.decodeTx(metaTx.data);\n```\n\nOr for a batch tx:\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction([{\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n}]);\nconst forwardFunctionArguments = proxyAccount.decodeBatchTx(metaTx.data);\n```","readmeFilename":"README.md","gitHead":"b7c53e191dbc2e62b0a90736bd54723aab9b22dc","_id":"@anydotcrypto/metatransactions@0.0.15-1","_nodeVersion":"11.10.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-ZWDt3puZS37SK5DOn5h3YgiE+yQt+wEda5UF0jU1H9F/jlxdWpk0MKTYytSBDVUgXpcnLykmD2IDwoWLDcykvA==","shasum":"962adaf5efc2d1d2dbba30612c9fd526ccf17c67","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.15-1.tgz","fileCount":317,"unpackedSize":2426846,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfGaMKCRA9TVsSAnZWagAAbiUP/j1F2m0DfLqfOnrUxaMd\nLGHQ6gTW5egGjQEzTFYEUaUIrJGqfzCVsb3Wq768qC8FFcZBLOrw3cDHr6t5\nJz3MR75UigMslonYG7Ac5SdAK2hl26TISTgca8GW24+C6fb8wWZlWRPJ7sYL\n2Vgh+zuWgDv06U4HJdRA8V2zi3Y7g8UUt6JYOwikoyXNk4gTR1l3XemJEwzn\nwgwnUL6r9ifzlNe7LrWV/0qAbdkWsMieED9SAztRb2MtuQSCcQsVe6liJ/9C\niu3YaCfz9nIcLfM9c9rOm2BFemPSxdtNn/We3YlRYqVZiVaPYJoaxv4GdmAr\norKxBcZl9LmcxGFAfVSzIPucFscl6nw2oDBinZrPTW9RXAfIwxtxHy5dQxLG\nz3SZquiDCPIE+c0PsO748EyYfUcZb8f5Sx+AbHU9/hYP8CEyEyG4nGoWoLYV\n8tGV+UZFgqIZwxZOwGYkALNX+Iy9Rozqv7MSt12aQS78qECwuReGfBhWvczN\nDbQlX54MfLT5f1ianEi/IiP9358duO6A8kxqm3jZXOTqqTe8/Yebi5vL3P85\n81ctQzTPKS4P3vmeFWZnywCkpoVQO2VXCPK0OQtJAZ1OcMg/T5toZqthVJVl\nQgNqDShTp2TFGMK/vgqx/GpuwcSvXhBWDH4FtxyUreZEozNDzoXtVHzPQKoE\ndsMK\r\n=lN4P\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICctMOBuBfgMUuIP74sudDgSyMldeMAJP2EBIPFvoRQyAiARf1zG6qCn0wY23fH1ZUGFt/n1SJzhgA0TRYLK9LwHjQ=="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.15-1_1595515657460_0.6505375498135255"},"_hasShrinkwrap":false},"0.0.15-2":{"name":"@anydotcrypto/metatransactions","version":"0.0.15-2","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-gnosis && npm run build-types","build-gnosis":"waffle waffle053.json","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deployScript.ts","generateSeed":"ts-node example/generateSeed.ts","echo-example":"ts-node example/proxyaccount/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build"},"devDependencies":{"@gnosis.pm/mock-contract":"^3.0.8","@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single RelayHub contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nOur meta-transaction library focuses on both approaches and we hope it benefits the community in the following way:\n\n- **A candidate RelayHub standard**: Our RelayHub.sol is a minimal and potential candidate for the \\_msgSender() standard.\n- **Minimal proxy contracts**: Our proxy contract is only responsible for forwarding and batching calls. It implements EIP-1167 to minimise storage/deployment overhead.\n- **Flexible replay protection:** We have implemented Nonce, MultiNonce and BitFlip, so you can decide if all transactions must be ordered, if you want up to N concurrent transactions, or to always support out-of-order transactions.\n\nOur repository is a protocol and relay-independent approach that any project can adopt. We hope it will make it easier for projects to tap into third party relayer APIs and to avoid re-implementing the wheel for reliable transaction infrastructure.\n\n# Getting started\n\nWe assume you have set up your nodejs environment and you simply need to plug-in our library.\n\n1. **Install**. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. **Environment**. Decide which network and replay protection to use.\n\nYou will need to import both the ChainID and Replay Protection into your code:\n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\n\nOur library currently supports MAINNET or ROPSTEN.\n\n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\n\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n\n```\n// ReplayProtection\nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\n\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. **msg.sender solution**. Decide which solution to msg.sender you want to use.\n\nWhile we support both the RelayHub and the ProxyContract in this library, we recommend the proxy account contract approach for most purposes as it works for all existing smart contracts.\n\nIf you want to learn more, check out [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub).\n\nFor the rest of the documentation, we only consider the proxy contract approach.\n\n4. **Instantiate**. Let's create the meta-transaction library with your preferred options!\n\nTo instantiate the proxy account forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract.\n\nImportant: Our library can authorise a meta-transaction if the proxy account contract does not yet exist (e.g. not deployed). Using the [MultiSend](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/ops/MultiSend.sol) contract, it is possible to meta-deploy the proxy contract and then execute the first meta-transaction in a single Ethereum Transaction. So there is no waiting/setup process.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nThe [Echo smart contract](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/ops/Echo.sol) is used for our example:\n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## How to use the Proxy Account contract\n\nThe [full example](https://github.com/anydotcrypto/metatransactions/blob/master/example/proxyaccount/echo.ts) is available and it covers:\n\n- Checking the proxy contract exists before deploying it.\n- Deploying the Echo Contract via the proxy contract\n- Sending a meta-transaction to the Echo Contract via the proxy contract.\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the proxy account contract.\n\n```\nconst isProxyDeployed = await forwarder.isContractDeployed();\nif (!isProxyDeployed) {\n    const minimalTx = await forwarder.createProxyContract();\n\n    // For our example we mimic the relayer API with a relayer wallet.\n    const proxyTx = await relayer.sendTransaction({\n      to: minimalTx.to,\n      data: minimalTx.data,\n    });\n\n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nSupply the following information:\n\n- **To** contract's address (required)\n- **Data** the function name and its arguments (required)\n- **Value** to be sent (in wei) - (optional)\n\nOnce you have settled on the message to echo, you can use this code sample to authorise the meta-transaction:\n\n```\n// Fetch the contract and the data.\nconst echo = new EchoFactory(user).attach(\"\");\nconst data = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    to: echo.address,\n    value: \"0\",\n    data: data,\n});\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTx.data,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Our library has taken care of the replay protection & constructing the transaction data for you.\n\nWell done!\n\n# Proxy Account Contract Functionality\n\nWe take this opportunity to cover each function in the library.\n\n## Instantiate the forwarder\n\nYou can use the factory to set up a new forwarder. It requires you to select the ChainID and the ReplayProtectionType. Note if you select MULTINONCE, then it generates 30 nonce queues by default. (e.g. up to 30 concurrent transactions at any single time).\n\n```\n  const proxyAccount = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.BITFLIP,\n    user\n  );\n```\n\n## Properties\n\nOnce you have instantiated the forwarder, then you can access the following properties:\n\n```\nconst proxyAccountAddress = proxyAccount.address;\nconst signer = proxyAccount.signer;\n```\n\nThanks to the ProxyDeployer, there is a one-to-one mapping for a signer's key and the proxy account contract address. The library will automatically compute the address and make it available via `proxyAccount.address`. Furthermore, the `Signer` is accessible via `proxyAccount.signer`.\n\n## Deploying the Proxy Contract\n\nThere are two helper functions:\n\n```\nconst isProxyDeployed = await proxyAccount.isContractDeployed();\nconst minimalTx = await proxyAccount.createProxyContract();\n```\n\nThe former lets you check if the proxy contract is already deployed. The latter prepares a meta-transaction that can be packed into an Ethereum Transaction to deploy the proxy contract. Note the `MinimalTx` only contains the fields `to, data`.\n\n## Authorising a meta-transaction.\n\nThere is a single function for authorising a meta-transaction:\n\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction({\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n});\n```\n\nIt returns a `MinimalTx` that only contains the fields `to, data` which can be packed into an Ethereum Transaction. This takes care of preparing the replay protection & wrapping the call so it can be processed by the proxy account contract.\n\nNote there is an additional `callType` field that can be used to decide if it is a `call` or a `delegatecall`. We only discuss call and advanced users can look at the contract on how to use delegatecall.\n\n## Authorising a meta-deployment.\n\nTo deploy use the signMetaTransaction function but replace the `to` argument with a `salt`:\n\n```\nconst initCode = new EchoFactory(user).getDeployTransaction().data!;\nconst value = \"0\";\nconst salt = \"0x123\";\nconst metaDeploy = await proxyAccount.signMetaTransaction({\n  initCode,\n  value,\n  salt\n});\n```\n\nThe `signAndEncodeMetaDeployment` function prepares a `MinimalTx` for the deployment. Again it only contains a `to,value,data` that can be packed in the Ethereum Transaction. In reality, it is using `delegatecall` from the proxy contract into a global deployer contract and then deploy the smart contract.\n\nThe `buildDeployedContractAddress` computes the address for the contract. It just requires the `initCode` and the `salt` used for the deployment.\n\n## Send a batch of meta-transactions\n\nYou need to prepare a list of transactions to use in the batch:\n\n```\nconst metaTxList = [{\n  to: msgSenderCon.address,\n  value: 0,\n  data: data,\n  revertOnFail: true,\n},\n{\n  data: initCode,\n  salt: \"v0.1\",\n  value: 0\n},\n{\n  to: echoCon.address,\n  value: 0,\n  data: data,\n  revertOnFail: false,\n}];\n```\n\nAn additional feature is `revertOnFail` which lets you decide if the entire batch of transactions should revert if the meta-transaction fails. Again, we omit `CallType` as it should only be used by advanced users and 99% of meta-transactions only require the `.call` functionality.\n\nNow you can batch the transactions:\n```\nconst minimalTx = await forwarder.signMetaTransaction(metaTxList);\n```\n\nThe `MinimalTx` contains the fields `to, data` that can be packed into an Ethereum Transaction. Each meta-transaction is processed in order by the proxy account contract.\n\n## Decoding a metatransaction\n\nYou can decode a metatransaction into it's consutituent parts by using the decodeTx or decodeBatchTx functions.\n\nFor a single tx:\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction({\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n});\nconst forwardFunctionArguments = proxyAccount.decodeTx(metaTx.data);\n```\n\nOr for a batch tx:\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction([{\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n}]);\nconst forwardFunctionArguments = proxyAccount.decodeBatchTx(metaTx.data);\n```","readmeFilename":"README.md","gitHead":"e0aac51dbdd7be55845e9a39349eeae729b1735a","_id":"@anydotcrypto/metatransactions@0.0.15-2","_nodeVersion":"11.10.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-dhGuyB0CsJCr2jEPHceMaCexY7XwmMa8ji44kkme5fBtxf5SngFec73J9g6ExVnFxfIp2OWFtKtPcRgIhUdkbg==","shasum":"31f834e75111210ed03b04c2c2eed901636b10a5","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.15-2.tgz","fileCount":2,"unpackedSize":13955,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfGbCDCRA9TVsSAnZWagAA3I0P/idTJYyqlay8DLUHiNjf\nSytcYpzkRiy6YZPbw5YsjwzLIi6LZCFxoMeJGfidKNdgG4zip/bY6KBQwF6n\nNl+tCw9tjxlUWyrnHAFK1tBUm7jAa+coIq/anUmaeh4nSDsctwQbetungXXU\nf49iMSEsxuEc/xhuiCRg+bZg14RFG95tRI1ZIyIAGZ8Br4U8ycG7169O8CpF\n4WKsvkP58rqXpmclF9yhSPpl7tYziugRYRp0Gl0WXaAzY4vjLNnIF3nRRSFG\nleqVSuOF+9cULHzGQ5zMN+rqfcBgn5Mks4lvFTECyIfzCVFDpv/awLFkb84W\nFGoXTskZlWTE/e/2Mje8apEZ03gNmJLYEFzF0hEjYibrSSIxpNRhhRomYddr\nR4TUn0XVYQMYMlxVqwgKm+k5aPvIzlyX9glfMp/JpjxSVDDlg1UvFt3eD6gA\nC4XjWdkDG4t7r+LNvP0StV0LSYpd3RlwfLfUQwJVt3ko5mzevetHwJ70F2aU\nu8D8H/IUMul/rwcSyp6VVJilW31Ey0PTmr2tXfmLNLss0qGeuXEAlHIyAWZj\nh3l9wlYrn2UIOqHF0Ni6phMx68aiDnGIr7dwpYj1IoHjyDgbdFwsvvg+I/+Y\nutydAxmRMe61dh4ltfluAx8H8dhcuVQG7Li8IFL+OvyslDw612kXQKhIY3hg\nUBc9\r\n=z+ML\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICxX7oxbzqJOznEV9BcLZvhEdo5PSw7rM3Is1LkI1Jy7AiB4jkvsRfy8s3oZ/J/nTXrJZDhlT3xe/N2f9P8Kj7HbxQ=="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.15-2_1595519106723_0.04586495165027449"},"_hasShrinkwrap":false},"0.0.15-3":{"name":"@anydotcrypto/metatransactions","version":"0.0.15-3","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-gnosis && npm run build-types","build-gnosis":"waffle waffle053.json","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deployScript.ts","generateSeed":"ts-node example/generateSeed.ts","echo-example":"ts-node example/proxyaccount/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build"},"devDependencies":{"@gnosis.pm/mock-contract":"^3.0.8","@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single RelayHub contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nOur meta-transaction library focuses on both approaches and we hope it benefits the community in the following way:\n\n- **A candidate RelayHub standard**: Our RelayHub.sol is a minimal and potential candidate for the \\_msgSender() standard.\n- **Minimal proxy contracts**: Our proxy contract is only responsible for forwarding and batching calls. It implements EIP-1167 to minimise storage/deployment overhead.\n- **Flexible replay protection:** We have implemented Nonce, MultiNonce and BitFlip, so you can decide if all transactions must be ordered, if you want up to N concurrent transactions, or to always support out-of-order transactions.\n\nOur repository is a protocol and relay-independent approach that any project can adopt. We hope it will make it easier for projects to tap into third party relayer APIs and to avoid re-implementing the wheel for reliable transaction infrastructure.\n\n# Getting started\n\nWe assume you have set up your nodejs environment and you simply need to plug-in our library.\n\n1. **Install**. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. **Environment**. Decide which network and replay protection to use.\n\nYou will need to import both the ChainID and Replay Protection into your code:\n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\n\nOur library currently supports MAINNET or ROPSTEN.\n\n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\n\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n\n```\n// ReplayProtection\nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\n\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. **msg.sender solution**. Decide which solution to msg.sender you want to use.\n\nWhile we support both the RelayHub and the ProxyContract in this library, we recommend the proxy account contract approach for most purposes as it works for all existing smart contracts.\n\nIf you want to learn more, check out [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub).\n\nFor the rest of the documentation, we only consider the proxy contract approach.\n\n4. **Instantiate**. Let's create the meta-transaction library with your preferred options!\n\nTo instantiate the proxy account forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract.\n\nImportant: Our library can authorise a meta-transaction if the proxy account contract does not yet exist (e.g. not deployed). Using the [MultiSend](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/ops/MultiSend.sol) contract, it is possible to meta-deploy the proxy contract and then execute the first meta-transaction in a single Ethereum Transaction. So there is no waiting/setup process.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nThe [Echo smart contract](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/ops/Echo.sol) is used for our example:\n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## How to use the Proxy Account contract\n\nThe [full example](https://github.com/anydotcrypto/metatransactions/blob/master/example/proxyaccount/echo.ts) is available and it covers:\n\n- Checking the proxy contract exists before deploying it.\n- Deploying the Echo Contract via the proxy contract\n- Sending a meta-transaction to the Echo Contract via the proxy contract.\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the proxy account contract.\n\n```\nconst isProxyDeployed = await forwarder.isContractDeployed();\nif (!isProxyDeployed) {\n    const minimalTx = await forwarder.createProxyContract();\n\n    // For our example we mimic the relayer API with a relayer wallet.\n    const proxyTx = await relayer.sendTransaction({\n      to: minimalTx.to,\n      data: minimalTx.data,\n    });\n\n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nSupply the following information:\n\n- **To** contract's address (required)\n- **Data** the function name and its arguments (required)\n- **Value** to be sent (in wei) - (optional)\n\nOnce you have settled on the message to echo, you can use this code sample to authorise the meta-transaction:\n\n```\n// Fetch the contract and the data.\nconst echo = new EchoFactory(user).attach(\"\");\nconst data = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    to: echo.address,\n    value: \"0\",\n    data: data,\n});\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTx.data,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Our library has taken care of the replay protection & constructing the transaction data for you.\n\nWell done!\n\n# Proxy Account Contract Functionality\n\nWe take this opportunity to cover each function in the library.\n\n## Instantiate the forwarder\n\nYou can use the factory to set up a new forwarder. It requires you to select the ChainID and the ReplayProtectionType. Note if you select MULTINONCE, then it generates 30 nonce queues by default. (e.g. up to 30 concurrent transactions at any single time).\n\n```\n  const proxyAccount = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.BITFLIP,\n    user\n  );\n```\n\n## Properties\n\nOnce you have instantiated the forwarder, then you can access the following properties:\n\n```\nconst proxyAccountAddress = proxyAccount.address;\nconst signer = proxyAccount.signer;\n```\n\nThanks to the ProxyDeployer, there is a one-to-one mapping for a signer's key and the proxy account contract address. The library will automatically compute the address and make it available via `proxyAccount.address`. Furthermore, the `Signer` is accessible via `proxyAccount.signer`.\n\n## Deploying the Proxy Contract\n\nThere are two helper functions:\n\n```\nconst isProxyDeployed = await proxyAccount.isContractDeployed();\nconst minimalTx = await proxyAccount.createProxyContract();\n```\n\nThe former lets you check if the proxy contract is already deployed. The latter prepares a meta-transaction that can be packed into an Ethereum Transaction to deploy the proxy contract. Note the `MinimalTx` only contains the fields `to, data`.\n\n## Authorising a meta-transaction.\n\nThere is a single function for authorising a meta-transaction:\n\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction({\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n});\n```\n\nIt returns a `MinimalTx` that only contains the fields `to, data` which can be packed into an Ethereum Transaction. This takes care of preparing the replay protection & wrapping the call so it can be processed by the proxy account contract.\n\nNote there is an additional `callType` field that can be used to decide if it is a `call` or a `delegatecall`. We only discuss call and advanced users can look at the contract on how to use delegatecall.\n\n## Authorising a meta-deployment.\n\nTo deploy use the signMetaTransaction function but replace the `to` argument with a `salt`:\n\n```\nconst initCode = new EchoFactory(user).getDeployTransaction().data!;\nconst value = \"0\";\nconst salt = \"0x123\";\nconst metaDeploy = await proxyAccount.signMetaTransaction({\n  initCode,\n  value,\n  salt\n});\n```\n\nThe `signAndEncodeMetaDeployment` function prepares a `MinimalTx` for the deployment. Again it only contains a `to,value,data` that can be packed in the Ethereum Transaction. In reality, it is using `delegatecall` from the proxy contract into a global deployer contract and then deploy the smart contract.\n\nThe `buildDeployedContractAddress` computes the address for the contract. It just requires the `initCode` and the `salt` used for the deployment.\n\n## Send a batch of meta-transactions\n\nYou need to prepare a list of transactions to use in the batch:\n\n```\nconst metaTxList = [{\n  to: msgSenderCon.address,\n  value: 0,\n  data: data,\n  revertOnFail: true,\n},\n{\n  data: initCode,\n  salt: \"v0.1\",\n  value: 0\n},\n{\n  to: echoCon.address,\n  value: 0,\n  data: data,\n  revertOnFail: false,\n}];\n```\n\nAn additional feature is `revertOnFail` which lets you decide if the entire batch of transactions should revert if the meta-transaction fails. Again, we omit `CallType` as it should only be used by advanced users and 99% of meta-transactions only require the `.call` functionality.\n\nNow you can batch the transactions:\n```\nconst minimalTx = await forwarder.signMetaTransaction(metaTxList);\n```\n\nThe `MinimalTx` contains the fields `to, data` that can be packed into an Ethereum Transaction. Each meta-transaction is processed in order by the proxy account contract.\n\n## Decoding a metatransaction\n\nYou can decode a metatransaction into it's consutituent parts by using the decodeTx or decodeBatchTx functions.\n\nFor a single tx:\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction({\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n});\nconst forwardFunctionArguments = proxyAccount.decodeTx(metaTx.data);\n```\n\nOr for a batch tx:\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction([{\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n}]);\nconst forwardFunctionArguments = proxyAccount.decodeBatchTx(metaTx.data);\n```","readmeFilename":"README.md","gitHead":"b3ee71b4fd7d8626a461746078352895bd007951","_id":"@anydotcrypto/metatransactions@0.0.15-3","_nodeVersion":"11.10.1","_npmVersion":"6.14.6","dist":{"integrity":"sha512-sE9dyoeCASLnVvEXSm3H2M0ZjJFIvmdLBMwwZ9bB5ci+wAOawdLcrGcJKMaVXpw0KifzZkcLOebHwoNPJ5YHXw==","shasum":"960f2f47d31dafe035326be38b04ec5572f5e23b","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.15-3.tgz","fileCount":317,"unpackedSize":2426892,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfGbS7CRA9TVsSAnZWagAAgWEP/jaFDAjwBQYkBcIWBGTa\nINf+31L9ARBEuBoxaUwwdkppSI8B8qDybbWkpm2pv/WsAwmgdKKOp5RPQ+I/\nkPr2exPfy2m8KtLKXTaA6ITqw/TJBNSNYvNQKCpUbTHKJGI21jMpAAjMDUCH\nxisakBh5W34J7PnMEq5fQFfdFQczOndqE590HSSs/0ISO1xDDdvdKo6IWImX\nNhcH3YHOfbdCMeiwlxqfTQVXmvBcovx//IihOuRSTxgJKWpo7Z05DJkD7EDP\nfee6DActQPoAKl5PK4uq7kFw3d6N3u/FdIoOAjrBPonqZM6e9QDBHBzS5Ldv\ntcwY5U7p60bajCeMBqNafZ8Pgjy/eAnMAgm7+7KaB4x0uLTZn9AY3hKzzR6s\nNHQHAU/zvLxUvFlg4IYlK+dAR1rVaO62LAYrKmqdJGv7yfPTW4a3Rm/J1b6f\ngCol9BNJj0ycs8gQIQhLvas+zDTfiN5tlXM2B5EHA28z/neHUpi+uzU3EjOo\ndV1CWy17N4pDih9VionyX6XhE4viW1eBLH3zoRwnbQix000m9Kh82SaIrofx\nSs+143uVbVr6vZHcAqO21m4PcpALk5YIbvg8Fm5HZXYnVuo0AJOCKctC6bIm\nw9aR0ozLzVO7XsK7IktQqoPuhxhCoQmu3it6MXnKgS4BfPYkegSsWFWe7Kr8\nTJS+\r\n=kdJ+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCpd30i2CTNcPgO4ejQkaQRQ2iOxng7cgAuVkGVmpFNKAIhAPnAP2vLdqPjyNmiTmSlw7IRtQfWvKKiv/pGjGUQz2Uz"}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.15-3_1595520186994_0.1675632310529136"},"_hasShrinkwrap":false},"0.0.15-4":{"name":"@anydotcrypto/metatransactions","version":"0.0.15-4","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"npm run publish-our-contracts && npm run publish-gnosis-contracts","publish-our-contracts":"mkdir ./dist && mkdir ./dist/typedContracts && mkdir ./dist/contracts && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","publish-gnosis-contracts":"mkdir ./dist/gnosisTypedContracts && cp -r ./src/gnosisTypedContracts/* ./dist/gnosisTypedContracts","deploy":"ts-node src/deployment/deployScript.ts","generateSeed":"ts-node example/generateSeed.ts","echo-example":"ts-node example/proxyaccount/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build"},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single RelayHub contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nOur meta-transaction library focuses on both approaches and we hope it benefits the community in the following way:\n\n- **A candidate RelayHub standard**: Our RelayHub.sol is a minimal and potential candidate for the \\_msgSender() standard.\n- **Minimal proxy contracts**: Our proxy contract is only responsible for forwarding and batching calls. It implements EIP-1167 to minimise storage/deployment overhead.\n- **Flexible replay protection:** We have implemented Nonce, MultiNonce and BitFlip, so you can decide if all transactions must be ordered, if you want up to N concurrent transactions, or to always support out-of-order transactions.\n\nOur repository is a protocol and relay-independent approach that any project can adopt. We hope it will make it easier for projects to tap into third party relayer APIs and to avoid re-implementing the wheel for reliable transaction infrastructure.\n\n# Getting started\n\nWe assume you have set up your nodejs environment and you simply need to plug-in our library.\n\n1. **Install**. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. **Environment**. Decide which network and replay protection to use.\n\nYou will need to import both the ChainID and Replay Protection into your code:\n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\n\nOur library currently supports MAINNET or ROPSTEN.\n\n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\n\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n\n```\n// ReplayProtection\nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\n\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. **msg.sender solution**. Decide which solution to msg.sender you want to use.\n\nWhile we support both the RelayHub and the ProxyContract in this library, we recommend the proxy account contract approach for most purposes as it works for all existing smart contracts.\n\nIf you want to learn more, check out [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub).\n\nFor the rest of the documentation, we only consider the proxy contract approach.\n\n4. **Instantiate**. Let's create the meta-transaction library with your preferred options!\n\nTo instantiate the proxy account forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract.\n\nImportant: Our library can authorise a meta-transaction if the proxy account contract does not yet exist (e.g. not deployed). Using the [MultiSend](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/ops/MultiSend.sol) contract, it is possible to meta-deploy the proxy contract and then execute the first meta-transaction in a single Ethereum Transaction. So there is no waiting/setup process.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nThe [Echo smart contract](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/ops/Echo.sol) is used for our example:\n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## How to use the Proxy Account contract\n\nThe [full example](https://github.com/anydotcrypto/metatransactions/blob/master/example/proxyaccount/echo.ts) is available and it covers:\n\n- Checking the proxy contract exists before deploying it.\n- Deploying the Echo Contract via the proxy contract\n- Sending a meta-transaction to the Echo Contract via the proxy contract.\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the proxy account contract.\n\n```\nconst isProxyDeployed = await forwarder.isContractDeployed();\nif (!isProxyDeployed) {\n    const minimalTx = await forwarder.createProxyContract();\n\n    // For our example we mimic the relayer API with a relayer wallet.\n    const proxyTx = await relayer.sendTransaction({\n      to: minimalTx.to,\n      data: minimalTx.data,\n    });\n\n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nSupply the following information:\n\n- **To** contract's address (required)\n- **Data** the function name and its arguments (required)\n- **Value** to be sent (in wei) - (optional)\n\nOnce you have settled on the message to echo, you can use this code sample to authorise the meta-transaction:\n\n```\n// Fetch the contract and the data.\nconst echo = new EchoFactory(user).attach(\"\");\nconst data = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    to: echo.address,\n    value: \"0\",\n    data: data,\n});\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTx.data,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Our library has taken care of the replay protection & constructing the transaction data for you.\n\nWell done!\n\n# Proxy Account Contract Functionality\n\nWe take this opportunity to cover each function in the library.\n\n## Instantiate the forwarder\n\nYou can use the factory to set up a new forwarder. It requires you to select the ChainID and the ReplayProtectionType. Note if you select MULTINONCE, then it generates 30 nonce queues by default. (e.g. up to 30 concurrent transactions at any single time).\n\n```\n  const proxyAccount = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.BITFLIP,\n    user\n  );\n```\n\n## Properties\n\nOnce you have instantiated the forwarder, then you can access the following properties:\n\n```\nconst proxyAccountAddress = proxyAccount.address;\nconst signer = proxyAccount.signer;\n```\n\nThanks to the ProxyDeployer, there is a one-to-one mapping for a signer's key and the proxy account contract address. The library will automatically compute the address and make it available via `proxyAccount.address`. Furthermore, the `Signer` is accessible via `proxyAccount.signer`.\n\n## Deploying the Proxy Contract\n\nThere are two helper functions:\n\n```\nconst isProxyDeployed = await proxyAccount.isContractDeployed();\nconst minimalTx = await proxyAccount.createProxyContract();\n```\n\nThe former lets you check if the proxy contract is already deployed. The latter prepares a meta-transaction that can be packed into an Ethereum Transaction to deploy the proxy contract. Note the `MinimalTx` only contains the fields `to, data`.\n\n## Authorising a meta-transaction.\n\nThere is a single function for authorising a meta-transaction:\n\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction({\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n});\n```\n\nIt returns a `MinimalTx` that only contains the fields `to, data` which can be packed into an Ethereum Transaction. This takes care of preparing the replay protection & wrapping the call so it can be processed by the proxy account contract.\n\nNote there is an additional `callType` field that can be used to decide if it is a `call` or a `delegatecall`. We only discuss call and advanced users can look at the contract on how to use delegatecall.\n\n## Authorising a meta-deployment.\n\nTo deploy use the signMetaTransaction function but replace the `to` argument with a `salt`:\n\n```\nconst initCode = new EchoFactory(user).getDeployTransaction().data!;\nconst value = \"0\";\nconst salt = \"0x123\";\nconst metaDeploy = await proxyAccount.signMetaTransaction({\n  initCode,\n  value,\n  salt\n});\n```\n\nThe `signAndEncodeMetaDeployment` function prepares a `MinimalTx` for the deployment. Again it only contains a `to,value,data` that can be packed in the Ethereum Transaction. In reality, it is using `delegatecall` from the proxy contract into a global deployer contract and then deploy the smart contract.\n\nThe `buildDeployedContractAddress` computes the address for the contract. It just requires the `initCode` and the `salt` used for the deployment.\n\n## Send a batch of meta-transactions\n\nYou need to prepare a list of transactions to use in the batch:\n\n```\nconst metaTxList = [{\n  to: msgSenderCon.address,\n  value: 0,\n  data: data,\n  revertOnFail: true,\n},\n{\n  data: initCode,\n  salt: \"v0.1\",\n  value: 0\n},\n{\n  to: echoCon.address,\n  value: 0,\n  data: data,\n  revertOnFail: false,\n}];\n```\n\nAn additional feature is `revertOnFail` which lets you decide if the entire batch of transactions should revert if the meta-transaction fails. Again, we omit `CallType` as it should only be used by advanced users and 99% of meta-transactions only require the `.call` functionality.\n\nNow you can batch the transactions:\n```\nconst minimalTx = await forwarder.signMetaTransaction(metaTxList);\n```\n\nThe `MinimalTx` contains the fields `to, data` that can be packed into an Ethereum Transaction. Each meta-transaction is processed in order by the proxy account contract.\n\n## Decoding a metatransaction\n\nYou can decode a metatransaction into it's consutituent parts by using the decodeTx or decodeBatchTx functions.\n\nFor a single tx:\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction({\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n});\nconst forwardFunctionArguments = proxyAccount.decodeTx(metaTx.data);\n```\n\nOr for a batch tx:\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction([{\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n}]);\nconst forwardFunctionArguments = proxyAccount.decodeBatchTx(metaTx.data);\n```","readmeFilename":"README.md","gitHead":"f50782db7fced9219b111f5cfdfce13e3eaef1f9","_id":"@anydotcrypto/metatransactions@0.0.15-4","_nodeVersion":"11.10.1","_npmVersion":"6.14.7","dist":{"integrity":"sha512-sOaej7NG8xNwZCgd4emdXQpkEbXjcgoz4JroKtf8adaMGIxRUG1RD6YqtOKgCBjOcQkH1yZ/06nX2p9jpfanxg==","shasum":"bf55a60b4c425b85272e96b6d598adf78c9df426","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.15-4.tgz","fileCount":67,"unpackedSize":1014966,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfIYxqCRA9TVsSAnZWagAAjjwP/jivcjevbtj3bIRhztVe\nd5chdAM7Ddb310mSoIZyhxHlDrlzLzyPDDMSWSvn91FWr3XOOwnNbV1Pp/SK\nT+eqNTs705PqR97WLyV0QATpvsqXAzmfvX8S5Zg9LTlX+8EComIgztW0O5t5\nZvqOS1dSiA4r8kcMyur6f/LsPHJrIkv6XRqmeut4vVH4CsdYHcFKum+wGsNx\nDd/Zzj6Ds5YFeOzCC/ZWT7XF1XzsiXM+EVsYQW6gnayrxV3SEXBCxXXcavuu\nsQFaYRbrgximrgg56Z0ssqZ6f5CTaxvPUeQK+Xgu1nI66NaJIpy02/yV/wr6\n8KbQ0/EzMsmr2KeQTntH95wJLR4qDLBJmVDebs8n9pOHZyBnqTB/vMttj2VY\nAqsKRoEBkDwxKWEtJfm6WQp5dj0fDHIhvytoY1ls54m3BtzTxNWX2SSizndI\nbEzNrSJyPX1BJ7a2pFHxLY1rCireIvK+GSfRjbkba6IqrB6YaCh7YBTeRjPo\nwTs52QLCIRXGrBs10EXeCwVbk5IdkYgNdohq1W2AFkCN5o/o8mKay7vFi5S5\n22fKDiw9gKyn+bVw9ERQbMoB8Hx7oALZ0753DSDgtZuBgW0P8jkR3SfVHmbw\nmgoTp0WjZ6kiKpMWz3BQB5G85mYcD38Tzx9utTi+RLS73PiIs0wNIThoJK3z\nLJoz\r\n=+Fwh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB+4MjY9ZWy/sjxf8YG41DZ5UAAgS5sAoYxFvqaADsP6AiAUiCpHny1rcYD2sN2NR5RAiNCItNCD+b2FQNCtXVCQig=="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.15-4_1596034154239_0.5456554314064965"},"_hasShrinkwrap":false},"0.0.15-5":{"name":"@anydotcrypto/metatransactions","version":"0.0.15-5","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deployScript.ts","generateSeed":"ts-node example/generateSeed.ts","echo-example":"ts-node example/proxyaccount/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build"},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single RelayHub contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nOur meta-transaction library focuses on both approaches and we hope it benefits the community in the following way:\n\n- **A candidate RelayHub standard**: Our RelayHub.sol is a minimal and potential candidate for the \\_msgSender() standard.\n- **Minimal proxy contracts**: Our proxy contract is only responsible for forwarding and batching calls. It implements EIP-1167 to minimise storage/deployment overhead.\n- **Flexible replay protection:** We have implemented Nonce, MultiNonce and BitFlip, so you can decide if all transactions must be ordered, if you want up to N concurrent transactions, or to always support out-of-order transactions.\n\nOur repository is a protocol and relay-independent approach that any project can adopt. We hope it will make it easier for projects to tap into third party relayer APIs and to avoid re-implementing the wheel for reliable transaction infrastructure.\n\n# Getting started\n\nWe assume you have set up your nodejs environment and you simply need to plug-in our library.\n\n1. **Install**. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. **Environment**. Decide which network and replay protection to use.\n\nYou will need to import both the ChainID and Replay Protection into your code:\n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\n\nOur library currently supports MAINNET or ROPSTEN.\n\n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\n\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n\n```\n// ReplayProtection\nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\n\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. **msg.sender solution**. Decide which solution to msg.sender you want to use.\n\nWhile we support both the RelayHub and the ProxyContract in this library, we recommend the proxy account contract approach for most purposes as it works for all existing smart contracts.\n\nIf you want to learn more, check out [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub).\n\nFor the rest of the documentation, we only consider the proxy contract approach.\n\n4. **Instantiate**. Let's create the meta-transaction library with your preferred options!\n\nTo instantiate the proxy account forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract.\n\nImportant: Our library can authorise a meta-transaction if the proxy account contract does not yet exist (e.g. not deployed). Using the [MultiSend](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/ops/MultiSend.sol) contract, it is possible to meta-deploy the proxy contract and then execute the first meta-transaction in a single Ethereum Transaction. So there is no waiting/setup process.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nThe [Echo smart contract](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/ops/Echo.sol) is used for our example:\n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## How to use the Proxy Account contract\n\nThe [full example](https://github.com/anydotcrypto/metatransactions/blob/master/example/proxyaccount/echo.ts) is available and it covers:\n\n- Checking the proxy contract exists before deploying it.\n- Deploying the Echo Contract via the proxy contract\n- Sending a meta-transaction to the Echo Contract via the proxy contract.\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the proxy account contract.\n\n```\nconst isProxyDeployed = await forwarder.isContractDeployed();\nif (!isProxyDeployed) {\n    const minimalTx = await forwarder.createProxyContract();\n\n    // For our example we mimic the relayer API with a relayer wallet.\n    const proxyTx = await relayer.sendTransaction({\n      to: minimalTx.to,\n      data: minimalTx.data,\n    });\n\n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nSupply the following information:\n\n- **To** contract's address (required)\n- **Data** the function name and its arguments (required)\n- **Value** to be sent (in wei) - (optional)\n\nOnce you have settled on the message to echo, you can use this code sample to authorise the meta-transaction:\n\n```\n// Fetch the contract and the data.\nconst echo = new EchoFactory(user).attach(\"\");\nconst data = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    to: echo.address,\n    value: \"0\",\n    data: data,\n});\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTx.data,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Our library has taken care of the replay protection & constructing the transaction data for you.\n\nWell done!\n\n# Proxy Account Contract Functionality\n\nWe take this opportunity to cover each function in the library.\n\n## Instantiate the forwarder\n\nYou can use the factory to set up a new forwarder. It requires you to select the ChainID and the ReplayProtectionType. Note if you select MULTINONCE, then it generates 30 nonce queues by default. (e.g. up to 30 concurrent transactions at any single time).\n\n```\n  const proxyAccount = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.BITFLIP,\n    user\n  );\n```\n\n## Properties\n\nOnce you have instantiated the forwarder, then you can access the following properties:\n\n```\nconst proxyAccountAddress = proxyAccount.address;\nconst signer = proxyAccount.signer;\n```\n\nThanks to the ProxyDeployer, there is a one-to-one mapping for a signer's key and the proxy account contract address. The library will automatically compute the address and make it available via `proxyAccount.address`. Furthermore, the `Signer` is accessible via `proxyAccount.signer`.\n\n## Deploying the Proxy Contract\n\nThere are two helper functions:\n\n```\nconst isProxyDeployed = await proxyAccount.isContractDeployed();\nconst minimalTx = await proxyAccount.createProxyContract();\n```\n\nThe former lets you check if the proxy contract is already deployed. The latter prepares a meta-transaction that can be packed into an Ethereum Transaction to deploy the proxy contract. Note the `MinimalTx` only contains the fields `to, data`.\n\n## Authorising a meta-transaction.\n\nThere is a single function for authorising a meta-transaction:\n\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction({\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n});\n```\n\nIt returns a `MinimalTx` that only contains the fields `to, data` which can be packed into an Ethereum Transaction. This takes care of preparing the replay protection & wrapping the call so it can be processed by the proxy account contract.\n\nNote there is an additional `callType` field that can be used to decide if it is a `call` or a `delegatecall`. We only discuss call and advanced users can look at the contract on how to use delegatecall.\n\n## Authorising a meta-deployment.\n\nTo deploy use the signMetaTransaction function but replace the `to` argument with a `salt`:\n\n```\nconst initCode = new EchoFactory(user).getDeployTransaction().data!;\nconst value = \"0\";\nconst salt = \"0x123\";\nconst metaDeploy = await proxyAccount.signMetaTransaction({\n  initCode,\n  value,\n  salt\n});\n```\n\nThe `signAndEncodeMetaDeployment` function prepares a `MinimalTx` for the deployment. Again it only contains a `to,value,data` that can be packed in the Ethereum Transaction. In reality, it is using `delegatecall` from the proxy contract into a global deployer contract and then deploy the smart contract.\n\nThe `buildDeployedContractAddress` computes the address for the contract. It just requires the `initCode` and the `salt` used for the deployment.\n\n## Send a batch of meta-transactions\n\nYou need to prepare a list of transactions to use in the batch:\n\n```\nconst metaTxList = [{\n  to: msgSenderCon.address,\n  value: 0,\n  data: data,\n  revertOnFail: true,\n},\n{\n  data: initCode,\n  salt: \"v0.1\",\n  value: 0\n},\n{\n  to: echoCon.address,\n  value: 0,\n  data: data,\n  revertOnFail: false,\n}];\n```\n\nAn additional feature is `revertOnFail` which lets you decide if the entire batch of transactions should revert if the meta-transaction fails. Again, we omit `CallType` as it should only be used by advanced users and 99% of meta-transactions only require the `.call` functionality.\n\nNow you can batch the transactions:\n```\nconst minimalTx = await forwarder.signMetaTransaction(metaTxList);\n```\n\nThe `MinimalTx` contains the fields `to, data` that can be packed into an Ethereum Transaction. Each meta-transaction is processed in order by the proxy account contract.\n\n## Decoding a metatransaction\n\nYou can decode a metatransaction into it's consutituent parts by using the decodeTx or decodeBatchTx functions.\n\nFor a single tx:\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction({\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n});\nconst forwardFunctionArguments = proxyAccount.decodeTx(metaTx.data);\n```\n\nOr for a batch tx:\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction([{\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n}]);\nconst forwardFunctionArguments = proxyAccount.decodeBatchTx(metaTx.data);\n```","readmeFilename":"README.md","gitHead":"711b3c0009a01032d0138bab8dbe558202324b45","_id":"@anydotcrypto/metatransactions@0.0.15-5","_nodeVersion":"11.10.1","_npmVersion":"6.14.7","dist":{"integrity":"sha512-S42UoLV0MA0xyP43DztWbe+5Mf2XP3kSL9e4rhpzUI1WgqKkoSISB7lmXKarX0oUDO4Vd4Jdo8WULMckw1+Z7w==","shasum":"7ede71e91bfbf8f3bcd73f3a5069c88be172a17e","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.15-5.tgz","fileCount":174,"unpackedSize":935538,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfIZFYCRA9TVsSAnZWagAAcRwP/1DyXVBz8M+hBnR99UG0\nE/44plnDnKRWM0wq3Z9FtEHhkZ710h2lp9FXykFIGhsXOqG0o9q802tAuyCp\nwXWEQHhQKcQ18ApwewfUr/uqJROIn/yWkgKeBDxQFzePKTxKpYkcHMSe1DDA\nYxI4pbqgYMyOKr7ykxf1HT3VOevBXVj52ehfFYBmZdvan7b2MczxBclmQ819\n/t+rMQglPsUU8wLUD01pmZePOI2UP6vYo0p+tSAoAuZovewC81dVKAGVwRwn\nKgDXYyevEBl09BrzwMzft8k9ZXAnggaio4kVmIxcNWQM2/rH4KeGR8va0Uv4\n/1WJ5hh0IWrRu51EHW1bZ7vN30O0ol0JV9VSzZHNSzvH7ZBOzqkhIsnSqSQA\n2SIRzSq8+9VorYTK38II7Oc1eD4XnsXBbWhBoRlcbKVustBOzGjMdEMo4YvK\n2I+EGzhNG6Roorn9lMw4kO5U3j7xjuViGu3XBFVZZvZ8gKSiDCJietFh5DyZ\nU10raaAUcmJa1XlO2l6onJuLSJ3lrLdA3pLjTf5gJiz0IBnjwqU0AOQgqEuF\npT6Pjk/0c184B5+p9jfjQm6l10gFhzm4XpV/IQB0paWbZHIxBxUrjRYU/42l\n5x3wUO76YaS+YFo8ebChcWbO4BpWKC3P7HKYHyKDHIL1IW3GMjcduqXek9Di\n7kCd\r\n=NIiN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCBJ+UYovd1W8C/weuqXnx62AOTp7KZMLWRhLa4rBB2+wIhAIDdYrgachGbufNetBd4KyeN7u/4tnPRtUoT7h2sUh6D"}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.15-5_1596035409143_0.2408382114353922"},"_hasShrinkwrap":false},"0.0.15-6":{"name":"@anydotcrypto/metatransactions","version":"0.0.15-6","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/gnosisTypedContracts/* ./dist/gnosisTypedContracts && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deployScript.ts","generateSeed":"ts-node example/generateSeed.ts","echo-example":"ts-node example/proxyaccount/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build"},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single UniverisalForwarder contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nOur meta-transaction library focuses on both approaches and we hope it benefits the community in the following way:\n\n- **A Univerisal Forwarder**: Our RelayHub.sol can be used for the \\_msgSender() standard.\n- **Minimal wallet contract**: Our proxy contract only requires 67k gas to deploy & 26k gas per transaction. It is minimal code and supports batching transactions. Supports exotic replay protection for out of order-transactions (bitflip) and N concurrent transactions (multinonmce). \n- **GnosisSafe**: We have incorporated GnosisSafe and our library tracks the replay protection nonce such that it is meta-transaction friendly. It is an audited wallet contract that is increasingly widely used. \n\n**Our repository is a protocol and relay-independent approach** that any project can adopt. We hope it will make it easier for projects to tap into third party relayer APIs and to avoid re-implementing the wheel for reliable transaction infrastructure.\n\n# Getting started\n\nWe assume you have set up your nodejs environment and you simply need to plug-in our library.\n\n1. **Install**. You need to install the NPM pacakge:\n\n```\nnpm i @anydotcrypto/metatransactions --save-dev\n```\n\n2. **Environment**. Decide which network and replay protection to use.\n\nYou will need to import both the ChainID and Replay Protection into your code:\n\n```\nimport { ChainID, ReplayProtectionType } from \"@anydotcrypto/metatransactions\";\n```\n\nOur library currently supports MAINNET or ROPSTEN.\n\n```\n// Blockchain ID (Mainnet = 3)\nChainID.MAINNET;\nChainID.ROPSTEN;\n```\n\nOur library has three types of replay protection (and more in-depth information can be [found here](https://github.com/PISAresearch/metamask-comp)):\n\n- **Nonce**: Same as Ethereum, it increments a nonce for every new transaction.\n- **Multinonce:** There are multiple replace-by-nonce queues, so it supports up to N concurrent transactions at any time.\n- **Bitflip:** There is no queue and all transactions are processed out of order (e.g. batch withdrawals).\n\nTo access the replay protection:\n\n```\n// ReplayProtection\nReplayProtectionType.NONCE // Single queue\nReplayProtectionType.MULTINONCE // N queues (default == 30 queues)\nReplayProtectionType.BITFLIP // Always out-of-order & concurrent\n```\n\nBoth MultiNonce and Bitflip support concurrent & out-of-order transactions by default. If you want to guarantee that all transactions are processed in order, then just set `ReplayProtectionType.NONCE`.\n\n3. **msg.sender solution**. Decide which solution to msg.sender you want to use.\n\nWhile we support both the RelayHub and the ProxyContract in this library, we recommend the proxy account contract approach for most purposes as it works for all existing smart contracts.\n\nIf you want to learn more, check out [Proxy Account Contracts vs the RelayHub](https://github.com/anydotcrypto/metatransactions#proxyaccount-vs-relayhub).\n\nFor the rest of the documentation, we only consider the proxy contract approach.\n\n4. **Instantiate**. Let's create the meta-transaction library with your preferred options!\n\nTo instantiate the proxy account forwarder:\n\n```\nconst signer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    signer\n );\n```\n\nThe forwarder links the signer's wallet to their proxy account contract.\n\nImportant: Our library can authorise a meta-transaction if the proxy account contract does not yet exist (e.g. not deployed). Using the [MultiSend](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/ops/MultiSend.sol) contract, it is possible to meta-deploy the proxy contract and then execute the first meta-transaction in a single Ethereum Transaction. So there is no waiting/setup process.\n\n# You are now ready to authorise a meta-transaction!\n\nWe will show how to authorise a meta-transaction using a proxy account contract or the relay hub.\n\n## Example Echo Contract\n\nThe [Echo smart contract](https://github.com/anydotcrypto/metatransactions/blob/master/src/contracts/ops/Echo.sol) is used for our example:\n\n```\npragma solidity ^0.6.2;\ncontract Echo {\n    event Broadcast(address signer, string message);\n    function submit(string memory _message) public\n    {\n        emit Broadcast(msg.sender, _message);\n    }\n}\n```\n\n## How to use the Proxy Account contract\n\nThe [full example](https://github.com/anydotcrypto/metatransactions/blob/master/example/proxyaccount/echo.ts) is available and it covers:\n\n- Checking the proxy contract exists before deploying it.\n- Deploying the Echo Contract via the proxy contract\n- Sending a meta-transaction to the Echo Contract via the proxy contract.\n\nLet's set up our forwarder and signer:\n\n```\nconst user = Wallet.Mnemonic(\"\");\nconst relayer = Wallet.Mnemonic(\"\");\nconst forwarder = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.MULTINONCE,\n    user\n);\n```\n\nWe can deploy the proxy account contract.\n\n```\nconst isProxyDeployed = await forwarder.isContractDeployed();\nif (!isProxyDeployed) {\n    const minimalTx = await forwarder.createProxyContract();\n\n    // For our example we mimic the relayer API with a relayer wallet.\n    const proxyTx = await relayer.sendTransaction({\n      to: minimalTx.to,\n      data: minimalTx.data,\n    });\n\n    // Wait 1 block confirmation\n    const proxyReceipt = await proxyTx.wait(1);\n}\n```\n\nSupply the following information:\n\n- **To** contract's address (required)\n- **Data** the function name and its arguments (required)\n- **Value** to be sent (in wei) - (optional)\n\nOnce you have settled on the message to echo, you can use this code sample to authorise the meta-transaction:\n\n```\n// Fetch the contract and the data.\nconst echo = new EchoFactory(user).attach(\"\");\nconst data = echo.interface.functions.submit.encode([\"hello\"]);\n\n// Sign the meta transaction & encode it.\nconst metaTx = await forwarder.signMetaTransaction({\n    to: echo.address,\n    value: \"0\",\n    data: data,\n});\n\nconst submitTicketTx = await relayer.sendTransaction({\n    to: metaTx.to,\n    data: metaTx.data,\n});\n\nconst submitTicketReceipt = await submitTicketTx.wait(1);\n```\n\nEasy right? You have just deployed the proxy account contract and sent a meta-transaction via the proxy account contract. Our library has taken care of the replay protection & constructing the transaction data for you.\n\nWell done!\n\n# Proxy Account Contract Functionality\n\nWe take this opportunity to cover each function in the library.\n\n## Instantiate the forwarder\n\nYou can use the factory to set up a new forwarder. It requires you to select the ChainID and the ReplayProtectionType. Note if you select MULTINONCE, then it generates 30 nonce queues by default. (e.g. up to 30 concurrent transactions at any single time).\n\n```\n  const proxyAccount = await new ProxyAccountForwarderFactory().createNew(\n    ChainID.ROPSTEN,\n    ReplayProtectionType.BITFLIP,\n    user\n  );\n```\n\n## Properties\n\nOnce you have instantiated the forwarder, then you can access the following properties:\n\n```\nconst proxyAccountAddress = proxyAccount.address;\nconst signer = proxyAccount.signer;\n```\n\nThanks to the ProxyDeployer, there is a one-to-one mapping for a signer's key and the proxy account contract address. The library will automatically compute the address and make it available via `proxyAccount.address`. Furthermore, the `Signer` is accessible via `proxyAccount.signer`.\n\n## Deploying the Proxy Contract\n\nThere are two helper functions:\n\n```\nconst isProxyDeployed = await proxyAccount.isContractDeployed();\nconst minimalTx = await proxyAccount.createProxyContract();\n```\n\nThe former lets you check if the proxy contract is already deployed. The latter prepares a meta-transaction that can be packed into an Ethereum Transaction to deploy the proxy contract. Note the `MinimalTx` only contains the fields `to, data`.\n\n## Authorising a meta-transaction.\n\nThere is a single function for authorising a meta-transaction:\n\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction({\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n});\n```\n\nIt returns a `MinimalTx` that only contains the fields `to, data` which can be packed into an Ethereum Transaction. This takes care of preparing the replay protection & wrapping the call so it can be processed by the proxy account contract.\n\nNote there is an additional `callType` field that can be used to decide if it is a `call` or a `delegatecall`. We only discuss call and advanced users can look at the contract on how to use delegatecall.\n\n## Authorising a meta-deployment.\n\nTo deploy use the signMetaTransaction function but replace the `to` argument with a `salt`:\n\n```\nconst initCode = new EchoFactory(user).getDeployTransaction().data!;\nconst value = \"0\";\nconst salt = \"0x123\";\nconst metaDeploy = await proxyAccount.signMetaTransaction({\n  initCode,\n  value,\n  salt\n});\n```\n\nThe `signAndEncodeMetaDeployment` function prepares a `MinimalTx` for the deployment. Again it only contains a `to,value,data` that can be packed in the Ethereum Transaction. In reality, it is using `delegatecall` from the proxy contract into a global deployer contract and then deploy the smart contract.\n\nThe `buildDeployedContractAddress` computes the address for the contract. It just requires the `initCode` and the `salt` used for the deployment.\n\n## Send a batch of meta-transactions\n\nYou need to prepare a list of transactions to use in the batch:\n\n```\nconst metaTxList = [{\n  to: msgSenderCon.address,\n  value: 0,\n  data: data,\n  revertOnFail: true,\n},\n{\n  data: initCode,\n  salt: \"v0.1\",\n  value: 0\n},\n{\n  to: echoCon.address,\n  value: 0,\n  data: data,\n  revertOnFail: false,\n}];\n```\n\nAn additional feature is `revertOnFail` which lets you decide if the entire batch of transactions should revert if the meta-transaction fails. Again, we omit `CallType` as it should only be used by advanced users and 99% of meta-transactions only require the `.call` functionality.\n\nNow you can batch the transactions:\n```\nconst minimalTx = await forwarder.signMetaTransaction(metaTxList);\n```\n\nThe `MinimalTx` contains the fields `to, data` that can be packed into an Ethereum Transaction. Each meta-transaction is processed in order by the proxy account contract.\n\n## Decoding a metatransaction\n\nYou can decode a metatransaction into it's consutituent parts by using the decodeTx or decodeBatchTx functions.\n\nFor a single tx:\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction({\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n});\nconst forwardFunctionArguments = proxyAccount.decodeTx(metaTx.data);\n```\n\nOr for a batch tx:\n```\nconst echoAddress = \"0x...\";\nconst data = echoContract.interface.functions.sendMessage.encode([\n  \"any.sender is nice\",\n]);\nconst metaTx = await proxyAccount.signMetaTransaction([{\n  to: echoAddress,\n  data: data,\n  value: \"0\"\n}]);\nconst forwardFunctionArguments = proxyAccount.decodeBatchTx(metaTx.data);\n```","readmeFilename":"README.md","gitHead":"a1d5797d7d02548218479760fb4d5c8d63d017b4","_id":"@anydotcrypto/metatransactions@0.0.15-6","_nodeVersion":"11.10.1","_npmVersion":"6.14.7","dist":{"integrity":"sha512-5tOjVWpwIxvznX+iKwruDtjCjpr2t9sK63uOORf/Wk9rtG1GbF0VBt/NtBhF44pZM8X8x9Blyhs7DJEsaaaYYA==","shasum":"3c887a0eacc7f202575861420f335a8f23702062","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.15-6.tgz","fileCount":184,"unpackedSize":1370364,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfIaJECRA9TVsSAnZWagAAzqEQAIueIx3RoAmDelizvAqI\n2K2VMh1FSdhS5Rr4854PbMgLiiZrwR/heHzmkseu/cgzn1Hbc1UsI40Ob4SI\nakhM9YkgX5b1vIFhdhxXgGl8iSysH/QXzuCFLw9GgrodadE9E9r+ELKZ8AgU\nwWsZx6vGmNstglp+NmZvb5HA9c1vfePdNNeHjRY4KidXy5+FPa9gpoxb5fmI\nHKrZgok2XbGz9digEC61Td0D6/RGtWqPvysyUj45RFr3/Uy31lwS5sfKB502\nuS+VnvD8SKHDzUweAtb/fKg2cWv48216DLUb+QFjo1L0vuAA59oc4tg67VmG\nH4YR1GtIoGna+enjr4fv/ULfC0evnlK73uxh2QpiRAJL7vuo35KMQwZdEclI\nTILtO+TdJ2K5QTBHaOs+ASaZIjQ38l9gx41JkGarcwEH1WxaCm8E12fNMZ1L\nY8ZLftKENir/B4/pOt3ZCxaIvrvd6AmDl7xN/xcs8fAO8x7stIhZQKiwDRTh\nXdO8VpBd3+tNzMxd0V56Q5IK5q/AX1lMnFdQQcjASg3coTY2nRUxUgmPFgt7\nFVMYC2VZ7NYE7/v40Xus5OXvKr4l398qHZ8nK7CWiaoFjlmIPnkhjUsGGjRe\nsa1GdiPEJe5oQnxgz+azGPC0gkoM+OHsyX4eWfb0bwnMH2miTKT6II0CWsdE\nWaZI\r\n=EEJK\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCyYzLq5seEzHfyCwhpG7e2762CwvV5GeZCk04T+VP+ZAIhAIuzQMAJVcaBh0XU/TZAoXbVFKvwILf0NhSOIUWBnTiy"}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.15-6_1596039747343_0.7729234856793941"},"_hasShrinkwrap":false},"0.0.16":{"name":"@anydotcrypto/metatransactions","version":"0.0.16","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/gnosisTypedContracts/* ./dist/gnosisTypedContracts && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deployScript.ts","generateSeed":"ts-node example/generateSeed.ts","proxy-echo-example":"ts-node example/proxyaccount/echo.ts","gnosis-echo-example":"ts-node example/gnosis/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build"},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"gitHead":"f34da89614bd84fcdf692b3cdb0997e93b284712","_id":"@anydotcrypto/metatransactions@0.0.16","_nodeVersion":"11.10.1","_npmVersion":"6.14.7","dist":{"integrity":"sha512-044KqliIwXW9FtU9lWEjQwGDJT80leA3rrfywcADKl4LEljTXrg0AI/ng0/MQvRxIseAX9ROQhWbUb0SWldhMA==","shasum":"8bffbadc07ad2f353253fa5476c86e848cfda2f5","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.16.tgz","fileCount":184,"unpackedSize":1363900,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfIsf1CRA9TVsSAnZWagAAnMQP/iQ+cIGGhA+9PDAJ9FOZ\na/G+ZymzukR5c5kLqA05E1Mrvyp2S6p0afg9wq5kPU/wG86D+aqZLdE9Wslg\n05fBLqKBp7dqEkguAnqkSeDot5oz6yLl+8Cec19BNwyuA8Q4NniQAUn/l6gG\nZoWr7WOWx9HKNZGya7YeVE8QlHIGKTTk/yxCWxnZradYnKFkBjuIXODIGDDK\nwSjlQUG9hBnZ2vSifBf0+Ouzf+TbtV73nTvfkn9FMTTTT4Z96gtImQgs1Xte\nWuBiuY7Sp0n37Pd5I3iRUidJ/xa2PNTesFgoT8aI9funUtuk2UR7Ly7xArvZ\nN+mMQh6P3WGPw9DmJftqWAWx5cfvjAI0YvK+MO22p/bHLSsWLVrLTNrfl7ek\n4vlC3r+nfIClMxUvMcYUcrbZRBESPUnFS2+AqgiPtZ4g45npcW04TDQfG+Tq\nIt8YQxOqZ27WLX/igJijq5sWHKY7UCMfwJRMZ2148KoJEG79MR/JT+JM2mDa\nLFfRBhQywbss7i6p3sIkigw5yIqo2k430xaqsKOTHOrRFxmEwK0tRhAjVrJ6\nKo3DK/mQiR8xHKr6FTEAumY3+xnkBLKBrWjqPWnO6Lu4m4TqkcO9hwNeNxmY\nRJg8fExCfZbEYuAQwl3Syj73RHDOp2mf4MQm2+akUiXl8Fm2C6UFzR87NpEC\n7R85\r\n=6y87\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQClSo/WINFAwF5yJ/pTUBkffxFeC/X4uL7GSL+h62KaqAIgWwijJQLDWupau1ScZiarz+wZEI9ejsbgDgi8AIdvhaM="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.16_1596114932790_0.1652119880981422"},"_hasShrinkwrap":false},"0.0.18":{"name":"@anydotcrypto/metatransactions","version":"0.0.18","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/gnosisTypedContracts/* ./dist/gnosisTypedContracts && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deployScript.ts","generateSeed":"ts-node example/generateSeed.ts","proxy-echo-example":"ts-node example/proxyaccount/echo.ts","gnosis-echo-example":"ts-node example/gnosis/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build"},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43","npm":"^6.14.4","ts-node":"^8.8.2","typechain":"^1.0.3","typechain-target-ethers":"^1.0.4","typescript":"^3.7.5"},"gitHead":"ea4dd1ebdbf7c666c66e4547f61f2527d1fc2278","_id":"@anydotcrypto/metatransactions@0.0.18","_nodeVersion":"11.10.1","_npmVersion":"6.14.7","dist":{"integrity":"sha512-O4kooy4f1ELvZbcthik5b6xW7XrhNlh3hpRlX3nQmaeV7FZyBRDAs3pPdHYO8Jls9fnMJRzbxLi3NjXb37harg==","shasum":"a8e8c251cc679b934bcd434c28a18da8bd63058a","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.18.tgz","fileCount":184,"unpackedSize":1363825,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfIvBjCRA9TVsSAnZWagAACTgP/2nmU11n+ZZXNVeFY3fL\ny9N7ZRhDE5dEdf/uuWc7crhmHgAwV1lUYQhlJKyoglfeph9DHXiLhSAfdgH9\noqR+ZBRi0jsJ+3IymYBPWHrhe1zQoolg9esgFWbW6OLE7CfPkw6npdVvIu9f\nyDvOD5J0jIqcA9SMwlnBGWnodxGDnsiL8NqRN16nZetlJiE1VUbXxzL4QByt\nizLLUJDSOpBJFbMdT5HbNwVuSwx8iv3meYaK+IiX1eQJjEbLrgAAeqjOaXxb\nQjEobYYIhG7FpFE69Ql8LAx6koQ4LaflGqmjT/cJevJjQ1VRQmBdx/pgh14m\nRI4b1oYBUiExuG1ekxFwe5M6AIUlIWXzUFFP7voymSjuQxBT0F1/nv93f3fH\nBCEbzAs2yaDSS8U47v6YJpdHnlV404QubjtEQjclVY53StCK/ox9Q8+5zSCB\npCyDuFT3gMTYaWFp+ANgoXjRLNARoBMnN+xwQ/pdJkDTUQoRa2kbjgop1IRE\nQIgvpS9r0YoRIfnFDLC36wfV+7JT2arMjXRVESBZC0mU+HwM/dxh5S/vDaqV\n/jSoCVZxXvlQ/65eqiT7mt+33QHoKF4bsVTNA5zV7V717gZfGSi1fwuRRXY/\nrCcL6nEznn8lAzyOjysy9Xa8yvXEwZxvdo/a8y/jsgxjyeWtvwH3VubXwZNi\n3X5A\r\n=3t9/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC00FWlIbBqYudze/ORPZ+Vtk9U9qErXGYZrdndBo4hnwIhAKL7GIYPIM9nnZ78yrCdoH2javeSkm064OybKXuU7IV6"}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.18_1596125283364_0.08631624669283977"},"_hasShrinkwrap":false},"0.0.19":{"name":"@anydotcrypto/metatransactions","version":"0.0.19","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/gnosisTypedContracts/* ./dist/gnosisTypedContracts && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deployScript.ts","generateSeed":"ts-node example/generateSeed.ts","proxy-echo-example":"ts-node example/proxyaccount/echo.ts","gnosis-echo-example":"ts-node example/gnosis/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build"},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0","ts-node":"^8.10.2","typechain":"^1.0.5","typechain-target-ethers":"^1.0.4","typescript":"^3.9.7"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43"},"gitHead":"b5972a8529551186ac18cc2d003733ad251a872a","_id":"@anydotcrypto/metatransactions@0.0.19","_nodeVersion":"11.14.0","_npmVersion":"6.13.1","dist":{"integrity":"sha512-xxnAPgQllW8fmu6+Tafdy9NWo1MEIGqu5dD45wkdYp5UKNIQZiuXcSeEDTT2AlNyofyIMNJvDITgjA9t6wFDxA==","shasum":"476f869e74732af5ce1b24d1988269ab60ca9926","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.19.tgz","fileCount":184,"unpackedSize":1363806,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfPk1uCRA9TVsSAnZWagAAXugP/0/OnxWvnflqBuKa45Ul\n0l0DNjwiJgeDN/KnR/0oa6R5rzIxfQFYwfWQpkQOO5mWr8h+/xB4usTseyqP\nnL8r+AWL9BUNtzop5vp/zhzX96pzWIldF5ehEkbbrJQLKonpMDKzBf7q3yEJ\n+6hNyPKZM+qQvlNK1WZ1dvhA7mH4r1NDWMWcr0i9jYEptrijyFmC6vDxqGTC\nxx697HsURfv6EO5Ip9L3LV0I77XVpyJcZ6fmbklL2oB5ZS4u2LM/+/AaeYHP\n2P1XIfYzwIdMawrGmsS7c0X1iP3jcXmEPCcKCX5ZBMKHpZ08FQCm17BV/Nxy\nHMUzAV+ncrODSH6ff4Gj2TPIk9o+hK6g9nXDrl12D6Su5KI2IIw0yKyN85Be\ngmncXLW7TSVYWvnQmbA7F9w0U2b3yUqBJQQPyby75vLxUo3lv4XEz0EjEi9T\nmZ//Z1lDljndHU/Va2HKvVeKfJehubUs4ZKWU2AMKOgYDs9CBK3IhN9SfZnE\np6U+nvD/wTie8MkQyn0/GGFr9chcj9lwJYcyfoTA1r6UZ0qpA0GXpjis6PUT\nuCq7ZOM65+yP9Id3fk7z/8ACYIySmD5QoKRabjpL3eNm5G2HwnQC53Ilf8Cp\nwAxjOR8CXOZS4kqLoNNnddNhoXkxXas6oeGCShFPmQ+gfidok8LNrg5sIsTK\nv1kH\r\n=DtX0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC7TxD8j+JDO4tpK2c+9SWHW62YwId8VMy3D2gZ3iJvmAiEA5dTjvbk7P8w5Iv7uDVHgE69J6w4pzn2LlxtItbw7oNk="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"yahgwai","email":"cpbuckland88@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.19_1597918574092_0.9277201603841316"},"_hasShrinkwrap":false},"0.0.20":{"name":"@anydotcrypto/metatransactions","version":"0.0.20","description":"A minimal approach for meta-transaction support.","main":"dist/index.js","types":"dist/index.d.ts","directories":{"lib":"dist","test":"test"},"scripts":{"build-test":"npm run clean && npm run build && npm run runtest","build-execute":"npm run build && npm run execute","build-just":"waffle waffle.json","build":"waffle waffle.json && npm run build-types","build-types":"typechain --target ethers --outDir ./src/typedContracts ./build/**/*.json && cp ./build/* ./src/typedContracts","build-ts":"tsc -p tsconfig.json","publish-contracts":"cp -r ./src/gnosisTypedContracts/* ./dist/gnosisTypedContracts && cp -r ./src/typedContracts/*.d.ts ./dist/typedContracts && cp ./build/* ./dist/typedContracts && cp -r ./src/contracts ./dist/contracts","deploy":"ts-node src/deployment/deployScript.ts","generateSeed":"ts-node example/generateSeed.ts","proxy-echo-example":"ts-node example/proxyaccount/echo.ts","gnosis-echo-example":"ts-node example/gnosis/echo.ts","runtest":"NODE_ENV=test mocha --require ts-node/register --extension 'test.ts' './test/**/*.test.ts' --exit","test":"npm run build && npm run runtest -- --timeout='30000'","clean":"rm -rf ./dist && rm -rf ./build"},"devDependencies":{"@types/bn.js":"^4.11.6","@types/chai":"^4.2.7","@types/mocha":"^5.2.7","@types/node":"^14.0.1","bn.js":"^5.1.1","chai":"^4.2.0","ethereum-doppelganger":"0.0.7","ethereum-waffle":"2.3.0-istanbul.0","mocha":"^7.0.0","ts-mockito":"^2.5.0","ts-node":"^8.10.2","typechain":"^1.0.5","typechain-target-ethers":"^1.0.4","typescript":"^3.9.7"},"dependencies":{"@openzeppelin/contracts":"3.0.0-beta.0","@pisa-research/test-utils":"^0.1.36","@pisa-research/utils":"^0.1.39","ethers":"^4.0.43"},"gitHead":"8d0a51b304ca656c72b48725dc3ab52fb2a2b20f","_id":"@anydotcrypto/metatransactions@0.0.20","_nodeVersion":"11.14.0","_npmVersion":"6.7.0","dist":{"integrity":"sha512-b0QJmfv4PCZIkShTavcYFmPIvk7C5DXiBoRsrUBdHG7lM9qYlgGo6dDxv583Oycgai1t3ecSun9Z3RKgyzH7Dw==","shasum":"edb07032baee5b9266d1b7e52685072f21bb360f","tarball":"https://registry.npmjs.org/@anydotcrypto/metatransactions/-/metatransactions-0.0.20.tgz","fileCount":184,"unpackedSize":1366281,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfSQ1qCRA9TVsSAnZWagAAer0P/RqcY5mmKDMcOfBXMatu\nsVJicuCq6iqxafxgWVkzK19DzED5QugCdqNF+p6cTokTy5Q0A4WM08PvEvY4\nPZK9jUz8mCk6t1vdN64YWGph4q3VsfwOXNLhLscZ5VG8Ii60qNKz1oKkXrU0\nN9ASm6f4f90Fh5hK5RwsS4tIWc6DPNLe143smnh/BzhyOZYyFamQNrUHCRHt\nSjqeyE4FOBz4fLyeQu02JPlc696IYnuOyIDw6fRkKIhCwrzVxsI3yo5zEZho\ntBkW98ln9py9CR0AC4MJyi4JkB3zx5lp3fCd0d/NBT0knVwyQUg6W+aMTlud\nesgWI7yS87/8oH1GhoGMmpKib51eQk7cWevPNxtW3lP35f+d9M83gA4cbG3W\nlMXf/PKaB5Jpbvr3GKHeNs+wTEiUBQ++7eQjARG52hDfhTKeFZZBqe7cIgtz\nenpnEkARQwiO2g0Sby3NI2H+AKfbRglMsZSiNIIj7QaSsTXPNJQ4URnuQV52\nPc5nNJZ7iFG8a9zQuO6md4fc4UTXgqOS0D6Oiyg0hEalPN7mDqCLt6rbxMli\nDF5hdnXII745v6CcHb1cnpNaScAnxC8iIH2h+jhEe7H727LRc59Kl+UCemDq\niWzCwHoCPuoimiYUpQm7Ss4Dz1DNMkpMn47cw8XFwqRq4ZcOmOnmuyHn5J/c\nykQw\r\n=vQHr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA8NvRsrZBFn/xeOipJxECCAXgZBODmlhtNzkyE0kBY4AiEAsL7j9kxaRiMWUx8eLUxlaA9+GXMvxZUnlgB7H2bwfi8="}]},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"_npmUser":{"name":"stonecoldpat","email":"stonecoldpat@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/metatransactions_0.0.20_1598623081551_0.6938985924558096"},"_hasShrinkwrap":false}},"time":{"created":"2020-04-13T14:11:03.925Z","0.0.1":"2020-04-13T14:11:04.340Z","modified":"2022-04-04T14:26:47.059Z","0.0.2":"2020-04-13T14:25:38.079Z","0.0.3-0":"2020-04-13T14:57:54.201Z","0.0.3-1":"2020-04-13T18:08:06.809Z","0.0.3-2":"2020-04-13T20:04:37.869Z","0.0.3-3":"2020-04-13T20:29:28.008Z","0.0.3-4":"2020-04-13T20:47:48.107Z","0.0.3":"2020-04-14T17:07:41.679Z","0.0.4":"2020-04-14T17:42:15.989Z","0.0.5":"2020-04-16T16:18:00.052Z","0.0.6":"2020-04-16T16:51:31.852Z","0.0.7-0":"2020-04-21T19:43:34.540Z","0.0.7-1":"2020-04-21T20:12:58.107Z","0.0.7":"2020-04-21T20:26:08.888Z","0.0.8":"2020-04-29T22:34:25.343Z","0.0.9":"2020-04-30T09:59:59.994Z","0.0.10":"2020-04-30T18:53:53.760Z","0.0.11-0":"2020-05-04T10:20:48.379Z","0.0.11-1":"2020-05-04T11:37:33.384Z","0.0.11-2":"2020-05-05T13:02:32.522Z","0.0.11-3":"2020-05-05T14:04:13.986Z","0.0.11-4":"2020-05-05T14:38:50.042Z","0.0.11-10":"2020-05-08T14:01:50.960Z","0.0.11":"2020-05-12T17:12:37.270Z","0.0.12":"2020-05-14T16:09:35.134Z","0.0.13-0":"2020-05-14T20:55:28.897Z","0.0.13-4":"2020-05-14T21:24:38.318Z","0.0.13-5":"2020-05-15T17:52:15.241Z","0.0.13-6":"2020-05-16T12:42:19.137Z","0.0.13-7":"2020-05-16T12:49:13.512Z","0.0.13-8":"2020-05-16T13:39:48.450Z","0.0.13-9":"2020-05-16T17:39:07.986Z","0.0.13-10":"2020-05-20T13:43:59.295Z","0.0.13-11":"2020-05-22T15:42:10.144Z","0.0.13-12":"2020-05-28T15:11:31.545Z","0.0.13-13":"2020-05-28T17:15:21.896Z","0.0.13-14":"2020-06-03T10:00:11.261Z","0.0.13-15":"2020-06-03T10:50:31.412Z","0.0.13":"2020-06-10T13:39:35.391Z","0.0.14":"2020-06-17T15:15:15.283Z","0.0.15-0":"2020-07-23T13:33:53.721Z","0.0.15-1":"2020-07-23T14:47:37.610Z","0.0.15-2":"2020-07-23T15:45:06.825Z","0.0.15-3":"2020-07-23T16:03:07.284Z","0.0.15-4":"2020-07-29T14:49:14.488Z","0.0.15-5":"2020-07-29T15:10:09.356Z","0.0.15-6":"2020-07-29T16:22:27.492Z","0.0.16":"2020-07-30T13:15:32.986Z","0.0.18":"2020-07-30T16:08:03.559Z","0.0.19":"2020-08-20T10:16:14.254Z","0.0.20":"2020-08-28T13:58:01.961Z"},"maintainers":[{"email":"stonecoldpat@gmail.com","name":"stonecoldpat"},{"email":"cpbuckland88@gmail.com","name":"yahgwai"}],"description":"A minimal approach for meta-transaction support.","readme":"# A Minimal Meta-Transaction Library\n\nEthereum transaction's intertwine the identity of who paid for the transaction (gas.payer) and who wants to execute a command (msg.sender). As a result, it is **not straight forward for Alice to pay the gas fee on behalf of Bob** who wants to execute a command in a smart contract. Until it is fixed at the platform level, then Alice and Bob must adopt a meta-transaction standard to support this functionality (e.g. transaction infrastructure as a service in a non-custodial manner).\n\nThere are two approaches:\n\n- **Proxy contract:** Every user has a proxy contract and all transactions are sent via the proxy contract. It is compatible with all existing smart contracts.\n- **\\_msgSender():** All transactions are sent via a single UniversalForwarder contract and the target contract must support the \\_msgSender() standard. It preserves the user's signing key address as their identity.\n\nOur meta-transaction library focuses on both approaches and we hope it benefits the community in the following way:\n\n- **A Universal Forwarder**: Our RelayHub.sol can be used for the \\_msgSender() standard.\n- **Minimal wallet contract**: Our proxy contract only requires 67k gas to deploy & 26k gas per transaction. It is minimal code and supports batching transactions. As well, its replay protection supports out of order-transactions (bitflip) and concurrent transactions (multinonce).\n- **GnosisSafe**: We have incorporated [GnosisSafe](https://github.com/gnosis/safe-contracts) and our library tracks the replay protection nonce such that it is meta-transaction friendly. It is an audited wallet contract that is increasingly widely used.\n\n**Our repository is a protocol and relay-independent approach** that any project can adopt. We hope it will make it easier for projects to tap into third party relayer APIs and to avoid re-implementing the wheel for reliable transaction infrastructure.\n\n# Getting started\n\nWe have put together a guide for the universal forwarder, proxy account and gnosis safe:\n\n- Universal Forwarder: Tutorial to be completed soon.\n- [GnosisSafe Forwarder](./gnosisSafe.md#gnosis-safe-forwarder): An audited wallet contract implementation by Gnosis and we follow the nonce signature path. Thus it is meta-transaction safe.\n- [ProxyAccount Forwarder](./proxyAccounts.md#proxy-account-forwarder): Our own wallet contract implementation (not audited) with flexible replay protection and minimal overhead.\n\nOur unit tests evaluate the gas costs for the wallet contracts:\n\n| Name               | Deploy Wallet | 1st Transaction | 2nd Transaction | 10 Transactions (AVG) | 100 Transactions (AVG) | Meta-deployment Echo Contract |\n| ------------------ | ------------- | --------------- | --------------- | --------------------- | ---------------------- | ----------------------------- |\n| Gnosis Safe        | 223,240       | 39,014          | 24,014          | 24,009                | 24,011                 | 24,9179                       |\n| Proxy (Bitflip)    | 67,303        | 39,718          | 24,698          | 24,701                | 24,704                 | 25,9423                       |\n| Proxy (Multinonce) | 67,303        | 39,490          | 39,502          | 39,521                | 27,228                 | 25,9239                       |\n\n**Deploy wallet**. Both proxy contracts are deployed using EIP-1167 which is the minimal clone factory technique. Whereas Gnosis Safe deploys a proxy contract using CREATE2 and then has ~5 storage operations during setup.\n\n**1st Transaction**. All wallet contracts must initially set the `nonce` field which results in a higher gas cost.\n\n**2nd Transaction**. Both Gnosis Safe and Proxy-bitflip are comparable as the `nonce` field is reused. Multinonce is higher as it supports multiple nonce queues. By default it maintains 10 queues and the implementation cycles through each nonce queue in turn.\n\n**10 Transactions**.Both Gnosis Safe and Proxy-bitflip are comparable. Multinonce is higher as it supports multiple nonce queues. By default it maintains 10 queues an\n\n**100 Transactions**. All wallet contracts have comparable gas costs. The nonce field is re-used for every new transaction. The gas cost for bitslip should be around 24k gas for 255 transactions, and then it needs to set a new `nonce` field which is 39k gas, then it will again be 24k gas for 255 transactions\n\n**Meta-deployment Echo Contract.** All wallet contracts have comparable gas costs for deploying an echo contract. Each wallet contract delegate calls into a global deployer and the echo contract is deployed using CREATE2. We recommend deploying the contract and then calling an init() method (to avoid any msg.sender issues during deployment).\n","readmeFilename":"README.md"}