diff --git a/packages/core/package.json b/packages/core/package.json index 0a6ec45..308e704 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -30,6 +30,7 @@ "typescript": "^4.3.5" }, "dependencies": { + "eth-sig-util": "^3.0.1", "ethers": "^5.4.4", "js-waku": "^0.10.0", "protons": "^2.0.1" diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 15784ea..ebc2035 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -52,12 +52,14 @@ class WakuVoting { endTime?: number ) { const pollInit = await PollInitMsg.create(signer, question, answers, pollType, minToken, endTime) - const payload = PollInit.encode(pollInit) - if (payload && pollInit) { - const wakuMessage = await WakuMessage.fromBytes(payload, this.pollInitTopic, { - timestamp: new Date(pollInit.timestamp), - }) - await this.waku?.relay.send(wakuMessage) + if (pollInit) { + const payload = PollInit.encode(pollInit) + if (payload) { + const wakuMessage = await WakuMessage.fromBytes(payload, this.pollInitTopic, { + timestamp: new Date(pollInit.timestamp), + }) + await this.waku?.relay.send(wakuMessage) + } } } diff --git a/packages/core/src/models/PollInitMsg.ts b/packages/core/src/models/PollInitMsg.ts index b4cdef9..22e6be2 100644 --- a/packages/core/src/models/PollInitMsg.ts +++ b/packages/core/src/models/PollInitMsg.ts @@ -1,8 +1,58 @@ import { PollType } from '../types/PollType' -import { BigNumber, utils } from 'ethers' +import { BigNumber, utils, Wallet } from 'ethers' import { JsonRpcSigner } from '@ethersproject/providers' import { PollInit } from 'protons' -import { Wallet } from 'ethers' + +type Message = { + owner: string + timestamp: number + question: string + answers: string[] + pollType: PollType + endTime: number + minToken: BigNumber | undefined +} + +export function createSignMsgParams(message: Message) { + const msgParams: any = { + domain: { + name: 'Waku polling', + version: '1', + }, + message: { + owner: message.owner, + timestamp: new Date(message.timestamp).toLocaleDateString(), + question: message.question, + answers: message.answers, + pollType: message.pollType === PollType.WEIGHTED ? 'Weighted' : 'Non weighted', + endTime: new Date(message.endTime).toLocaleDateString(), + }, + primaryType: 'Mail', + types: { + EIP712Domain: [ + { name: 'name', type: 'string' }, + { name: 'version', type: 'string' }, + ], + Mail: [ + { name: 'owner', type: 'address' }, + { name: 'timestamp', type: 'string' }, + { name: 'question', type: 'string' }, + { name: 'answers', type: 'string[]' }, + { name: 'pollType', type: 'string' }, + { name: 'endTime', type: 'string' }, + ], + }, + } + + if (message.pollType === PollType.NON_WEIGHTED) { + if (message.minToken) { + msgParams.message = { ...msgParams.message, minToken: message.minToken.toString() } + msgParams.types.Mail.push({ name: 'minToken', type: 'uint256' }) + } + } + return msgParams +} + export class PollInitMsg { public owner: string public timestamp: number @@ -37,14 +87,15 @@ export class PollInitMsg { this.signature = signature } - static async create( + static async _createWithSignFunction( + signFunction: (params: string[]) => Promise, signer: JsonRpcSigner | Wallet, question: string, answers: string[], pollType: PollType, minToken?: BigNumber, endTime?: number - ): Promise { + ): Promise { const owner = await signer.getAddress() const timestamp = Date.now() let newEndTime = timestamp + 10000000 @@ -52,32 +103,48 @@ export class PollInitMsg { newEndTime = endTime } - const msg: (string | number | BigNumber | PollType)[] = [ + if (pollType === PollType.NON_WEIGHTED && !minToken) { + minToken = BigNumber.from(1) + } + + const params = createSignMsgParams({ owner, timestamp, question, - answers.join(), + answers, pollType, - newEndTime, - ] - const types = ['address', 'uint256', 'string', 'string', 'uint8', 'uint256'] - if (pollType === PollType.NON_WEIGHTED) { - if (minToken) { - msg.push(minToken) - } else { - msg.push(BigNumber.from(1)) - minToken = BigNumber.from(1) - } - types.push('uint256') + endTime: newEndTime, + minToken, + }) + + const signature = await signFunction([owner, JSON.stringify(params)]) + if (!signature) { + return undefined } - const packedData = utils.arrayify(utils.solidityPack(types, msg)) - const signature = await signer.signMessage(packedData) const id = utils.solidityKeccak256(['address', 'uint256'], [owner, timestamp]) return new PollInitMsg(id, owner, signature, timestamp, question, answers, pollType, newEndTime, minToken) } - static fromProto(payload: PollInit) { + static async create( + signer: JsonRpcSigner | Wallet, + question: string, + answers: string[], + pollType: PollType, + minToken?: BigNumber, + endTime?: number + ): Promise { + const signFunction = async (params: string[]) => { + if ('send' in signer.provider) { + return signer.provider.send('eth_signTypedData_v4', params) + } else { + return undefined + } + } + return this._createWithSignFunction(signFunction, signer, question, answers, pollType, minToken, endTime) + } + + static fromProto(payload: PollInit, recoverFunction: ({ data, sig }: { data: any; sig: string }) => string) { const owner = utils.getAddress(utils.hexlify(payload.owner)) const timestamp = payload.timestamp const question = payload.question @@ -85,29 +152,21 @@ export class PollInitMsg { const pollType = payload.pollType const endTime = payload.endTime const signature = utils.hexlify(payload.signature) - let minToken = payload.minToken ? BigNumber.from(payload.minToken) : undefined + const minToken = payload.minToken ? BigNumber.from(payload.minToken) : undefined - const msg: (string | number | BigNumber | PollType)[] = [ + const params = createSignMsgParams({ owner, timestamp, question, - answers.join(), - pollType, + answers, endTime, - ] - const types = ['address', 'uint256', 'string', 'string', 'uint8', 'uint256'] - if (pollType === PollType.NON_WEIGHTED) { - if (minToken) { - msg.push(minToken) - types.push('uint256') - } else { - return undefined - } - } else { - minToken = undefined - } - const packedData = utils.arrayify(utils.solidityPack(types, msg)) - const verifiedAddress = utils.verifyMessage(packedData, signature) + minToken, + pollType, + }) + const verifiedAddress = recoverFunction({ + data: params, + sig: signature, + }) if (verifiedAddress != owner) { return undefined } diff --git a/packages/core/src/utils/proto/PollInit.ts b/packages/core/src/utils/proto/PollInit.ts index 2e0c993..96cf7f3 100644 --- a/packages/core/src/utils/proto/PollInit.ts +++ b/packages/core/src/utils/proto/PollInit.ts @@ -2,6 +2,7 @@ import protons, { PollInit } from 'protons' import { PollType } from '../../types/PollType' import { utils } from 'ethers' import { PollInitMsg } from '../../models/PollInitMsg' +import { recoverTypedSignature_v4 } from 'eth-sig-util' const proto = protons(` message PollInit { @@ -46,7 +47,11 @@ export function encode(pollInit: PollInitMsg) { } } -export function decode(payload: Uint8Array, timestamp: Date | undefined) { +export function decode( + payload: Uint8Array, + timestamp: Date | undefined, + recoverFunction?: ({ data, sig }: { data: any; sig: string }) => string +) { try { const msg = proto.PollInit.decode(payload) if (!timestamp || timestamp.getTime() != msg.timestamp) { @@ -61,7 +66,10 @@ export function decode(payload: Uint8Array, timestamp: Date | undefined) { msg.endTime && msg.signature ) { - return PollInitMsg.fromProto(msg) + if (recoverFunction) { + return PollInitMsg.fromProto(msg, recoverFunction) + } + return PollInitMsg.fromProto(msg, (e) => utils.getAddress(recoverTypedSignature_v4(e))) } } catch { return undefined diff --git a/packages/core/test/models/PollInitMsg.test.ts b/packages/core/test/models/PollInitMsg.test.ts index a382eb2..766dbb8 100644 --- a/packages/core/test/models/PollInitMsg.test.ts +++ b/packages/core/test/models/PollInitMsg.test.ts @@ -1,82 +1,117 @@ import { expect } from 'chai' -import { PollInitMsg } from '../../src/models/PollInitMsg' +import { createSignMsgParams, PollInitMsg } from '../../src/models/PollInitMsg' import { MockProvider } from 'ethereum-waffle' import { PollType } from '../../src/types/PollType' -import { BigNumber, utils } from 'ethers' +import { BigNumber } from 'ethers' describe('PollInitMsg', () => { const provider = new MockProvider() const [alice] = provider.getWallets() it('success', async () => { - const poll = await PollInitMsg.create(alice, 'test', ['one', 'two', 'three'], PollType.WEIGHTED) + const poll = await PollInitMsg._createWithSignFunction( + async (params) => params.join(), + alice, + 'test', + ['one', 'two', 'three'], + PollType.WEIGHTED + ) expect(poll).to.not.be.undefined - expect(poll.owner).to.eq(alice.address) - expect(poll.endTime).to.eq(poll.timestamp + 10000000) - expect(poll.answers).to.deep.eq(['one', 'two', 'three']) - expect(poll.minToken).to.be.undefined - expect(poll.pollType).to.eq(PollType.WEIGHTED) - expect(poll.question).to.eq('test') + if (poll) { + expect(poll.owner).to.eq(alice.address) + expect(poll.endTime).to.eq(poll.timestamp + 10000000) + expect(poll.answers).to.deep.eq(['one', 'two', 'three']) + expect(poll.minToken).to.be.undefined + expect(poll.pollType).to.eq(PollType.WEIGHTED) + expect(poll.question).to.eq('test') - const types = ['address', 'uint256', 'string', 'string', 'uint8', 'uint256'] - const msg = [poll.owner, poll.timestamp, poll.question, poll.answers.join(), poll.pollType, poll.endTime] - const packedData = utils.arrayify(utils.solidityPack(types, msg)) - - const verifiedAddress = utils.verifyMessage(packedData, poll.signature) - expect(verifiedAddress).to.eq(alice.address) + expect(poll.signature).to.eq( + [ + poll.owner, + JSON.stringify( + createSignMsgParams({ + owner: poll.owner, + answers: poll.answers, + endTime: poll.endTime, + pollType: poll.pollType, + minToken: poll.minToken, + question: poll.question, + timestamp: poll.timestamp, + }) + ), + ].join() + ) + } }) it('success NON_WEIGHTED', async () => { - const poll = await PollInitMsg.create( + const poll = await PollInitMsg._createWithSignFunction( + async (params) => params.join(), alice, 'test', ['one', 'two', 'three'], PollType.NON_WEIGHTED, BigNumber.from(123) ) - + expect(poll).to.not.be.undefined expect(poll?.minToken?.toNumber()).to.eq(123) - - const types = ['address', 'uint256', 'string', 'string', 'uint8', 'uint256', 'uint256'] - const msg = [ - poll.owner, - poll.timestamp, - poll.question, - poll.answers.join(), - poll.pollType, - poll.endTime, - poll.minToken, - ] - const packedData = utils.arrayify(utils.solidityPack(types, msg)) - - const verifiedAddress = utils.verifyMessage(packedData, poll.signature) - expect(verifiedAddress).to.eq(alice.address) + if (poll) { + expect(poll.signature).to.eq( + [ + poll.owner, + JSON.stringify( + createSignMsgParams({ + owner: poll.owner, + answers: poll.answers, + endTime: poll.endTime, + pollType: poll.pollType, + minToken: poll.minToken, + question: poll.question, + timestamp: poll.timestamp, + }) + ), + ].join() + ) + } }) it('NON_WEIGHTED no minToken', async () => { - const poll = await PollInitMsg.create(alice, 'test', ['one', 'two', 'three'], PollType.NON_WEIGHTED) + const poll = await PollInitMsg._createWithSignFunction( + async (params) => params.join(), + alice, + 'test', + ['one', 'two', 'three'], + PollType.NON_WEIGHTED + ) expect(poll?.minToken?.toNumber()).to.eq(1) + expect(poll).to.not.be.undefined + if (poll) { + const msg = createSignMsgParams({ + owner: poll.owner, + answers: poll.answers, + endTime: poll.endTime, + pollType: poll.pollType, + minToken: poll.minToken, + question: poll.question, + timestamp: poll.timestamp, + }) - const types = ['address', 'uint256', 'string', 'string', 'uint8', 'uint256', 'uint256'] - const msg = [ - poll.owner, - poll.timestamp, - poll.question, - poll.answers.join(), - poll.pollType, - poll.endTime, - poll.minToken, - ] - const packedData = utils.arrayify(utils.solidityPack(types, msg)) - - const verifiedAddress = utils.verifyMessage(packedData, poll.signature) - expect(verifiedAddress).to.eq(alice.address) + expect(poll.signature).to.eq([poll.owner, JSON.stringify(msg)].join()) + } }) it('specific end time', async () => { - const poll = await PollInitMsg.create(alice, 'test', ['one', 'two', 'three'], PollType.NON_WEIGHTED, undefined, 100) + const poll = await PollInitMsg._createWithSignFunction( + async () => 'a', + alice, + 'test', + ['one', 'two', 'three'], + PollType.NON_WEIGHTED, + undefined, + 100 + ) expect(poll?.endTime).to.eq(100) }) diff --git a/packages/core/test/utils/proto/PollInit.test.ts b/packages/core/test/utils/proto/PollInit.test.ts index a31cdb0..ff90ee1 100644 --- a/packages/core/test/utils/proto/PollInit.test.ts +++ b/packages/core/test/utils/proto/PollInit.test.ts @@ -9,13 +9,20 @@ describe('PollInit', () => { const provider = new MockProvider() const [alice] = provider.getWallets() it('success', async () => { - const data = await PollInitMsg.create(alice, 'whats up', ['ab', 'cd', 'ef'], PollType.WEIGHTED) - - const payload = PollInit.encode(data) - - expect(payload).to.not.be.undefined - if (payload) { - expect(PollInit.decode(payload, new Date(data.timestamp))).to.deep.eq(data) + const data = await PollInitMsg._createWithSignFunction( + async () => '0x01', + alice, + 'whats up', + ['ab', 'cd', 'ef'], + PollType.WEIGHTED + ) + expect(data).to.not.be.undefined + if (data) { + const payload = PollInit.encode(data) + expect(payload).to.not.be.undefined + if (payload) { + expect(PollInit.decode(payload, new Date(data.timestamp), () => data.owner)).to.deep.eq(data) + } } }) @@ -28,29 +35,43 @@ describe('PollInit', () => { }) it('NON_WEIGHTED init', async () => { - const data = await PollInitMsg.create( + const data = await PollInitMsg._createWithSignFunction( + async () => '0x01', alice, 'whats up', ['ab', 'cd', 'ef'], PollType.NON_WEIGHTED, BigNumber.from(10) ) - - const payload = PollInit.encode(data) - expect(payload).to.not.be.undefined - if (payload) { - expect(PollInit.decode(payload, new Date(data.timestamp))).to.deep.eq(data) + expect(data).to.not.be.undefined + if (data) { + const payload = PollInit.encode(data) + expect(payload).to.not.be.undefined + if (payload) { + expect(PollInit.decode(payload, new Date(data.timestamp), () => data.owner)).to.deep.eq(data) + } } }) it('NON_WEIGHTED no min token', async () => { - const data = await PollInitMsg.create(alice, 'whats up', ['ab', 'cd', 'ef'], PollType.NON_WEIGHTED) + const data = await PollInitMsg._createWithSignFunction( + async () => '0x01', + alice, + 'whats up', + ['ab', 'cd', 'ef'], + PollType.NON_WEIGHTED + ) + expect(data).to.not.be.undefined + if (data) { + const payload = PollInit.encode(data) - const payload = PollInit.encode(data) - - expect(payload).to.not.be.undefined - if (payload) { - expect(PollInit.decode(payload, new Date(data.timestamp))).to.deep.eq({ ...data, minToken: BigNumber.from(1) }) + expect(payload).to.not.be.undefined + if (payload) { + expect(PollInit.decode(payload, new Date(data.timestamp), () => data.owner)).to.deep.eq({ + ...data, + minToken: BigNumber.from(1), + }) + } } }) }) diff --git a/packages/example/package.json b/packages/example/package.json index b1bd599..35327d2 100644 --- a/packages/example/package.json +++ b/packages/example/package.json @@ -14,6 +14,7 @@ }, "dependencies": { "@status-waku-voting/react-components": "link:../react-components", + "assert": "^2.0.0", "buffer": "^6.0.3", "crypto-browserify": "^3.12.0", "prettier": "^2.3.2", diff --git a/packages/example/webpack.config.js b/packages/example/webpack.config.js index 3e9df11..22624ea 100644 --- a/packages/example/webpack.config.js +++ b/packages/example/webpack.config.js @@ -22,7 +22,8 @@ module.exports = (env) => { fallback: { "buffer": require.resolve("buffer/"), "crypto": require.resolve("crypto-browserify"), - "stream": require.resolve("stream-browserify") + "stream": require.resolve("stream-browserify"), + "assert": require.resolve("assert") } }, module: { diff --git a/packages/react-components/src/index.tsx b/packages/react-components/src/index.tsx index 7f218e1..108bf74 100644 --- a/packages/react-components/src/index.tsx +++ b/packages/react-components/src/index.tsx @@ -5,9 +5,7 @@ import { PollList } from './PollList' import styled from 'styled-components' import { PollType } from '@status-waku-voting/core/dist/esm/src/types/PollType' -const ethereum = (window as any).ethereum - -const provider = new providers.Web3Provider(ethereum) +const provider = new providers.Web3Provider((window as any).ethereum) type ExampleProps = { appName: string @@ -24,14 +22,13 @@ function Example({ appName }: ExampleProps) { const [selectedType, setSelectedType] = useState(PollType.WEIGHTED) useEffect(() => { - ethereum.ethereum.on('accountsChanged', async () => { + provider.on('accountsChanged', async () => { provider.send('eth_requestAccounts', []) setSigner(provider.getSigner()) }) WakuVoting.create(appName, '0x01').then((e) => setWakuVoting(e)) provider.send('eth_requestAccounts', []) }, []) - return ( {showNewPollBox && ( diff --git a/yarn.lock b/yarn.lock index 729f6ec..baf7e5a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -895,8 +895,8 @@ "@status-waku-voting/core@link:packages/core": version "1.0.0" dependencies: + eth-sig-util "^3.0.1" ethers "^5.4.4" - js-waku "^0.10.0" protons "^2.0.1" "@status-waku-voting/react-components@link:packages/react-components": @@ -1103,9 +1103,9 @@ integrity sha512-zxrTNFl9Z8boMJXs6ieqZP0wAhvkdzmHSxTlJabM16cf5G9xBc1uPRH5Bbv2omEDDiM8MzTfqTJXBf0Ba4xFWA== "@types/node@>=13.7.0": - version "16.4.13" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.4.13.tgz#7dfd9c14661edc65cccd43a29eb454174642370d" - integrity sha512-bLL69sKtd25w7p1nvg9pigE4gtKVpGTPojBFLMkGHXuUgap2sLqQt2qUnqmVCDfzGUL0DRNZP+1prIZJbMeAXg== + version "16.6.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.6.0.tgz#0d5685f85066f94e97f19e8a67fe003c5fadacc4" + integrity sha512-OyiZPohMMjZEYqcVo/UJ04GyAxXOJEZO/FpzyXxcH4r/ArrVoXHf4MbUrkLp0Tz7/p1mMKpo5zJ6ZHl8XBNthQ== "@types/node@^12.12.6": version "12.20.19" @@ -1825,6 +1825,16 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= +assert@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-2.0.0.tgz#95fc1c616d48713510680f2eaf2d10dd22e02d32" + integrity sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A== + dependencies: + es6-object-assign "^1.1.0" + is-nan "^1.2.1" + object-is "^1.0.1" + util "^0.12.0" + assertion-error@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" @@ -1896,6 +1906,11 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== +available-typed-arrays@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.4.tgz#9e0ae84ecff20caae6a94a1c3bc39b955649b7a9" + integrity sha512-SA5mXJWrId1TaQjfxUYghbqQ/hYioKmLJvPJyDuYRtXXenFNMjj4hSSt1Cf1xsuXSXrtxrVC5Ot4eU6cOtBDdA== + aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" @@ -3991,7 +4006,7 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2, es-abstract@^1.18.2: +es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2, es-abstract@^1.18.2, es-abstract@^1.18.5: version "1.18.5" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.5.tgz#9b10de7d4c206a3581fd5b2124233e04db49ae19" integrity sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA== @@ -4046,6 +4061,11 @@ es6-iterator@~2.0.3: es5-ext "^0.10.35" es6-symbol "^3.1.1" +es6-object-assign@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c" + integrity sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw= + es6-promisify@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-6.1.1.tgz#46837651b7b06bf6fff893d03f29393668d01621" @@ -4341,6 +4361,16 @@ eth-sig-util@^1.4.2: ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" ethereumjs-util "^5.1.1" +eth-sig-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-3.0.1.tgz#8753297c83a3f58346bd13547b59c4b2cd110c96" + integrity sha512-0Us50HiGGvZgjtWTyAI/+qTzYPMLy5Q451D0Xy68bxq1QMWdoOddDwGvsqcFT27uohKgalM9z/yxplyt+mY2iQ== + dependencies: + ethereumjs-abi "^0.6.8" + ethereumjs-util "^5.1.1" + tweetnacl "^1.0.3" + tweetnacl-util "^0.15.0" + eth-tx-summary@^3.1.2: version "3.2.4" resolved "https://registry.yarnpkg.com/eth-tx-summary/-/eth-tx-summary-3.2.4.tgz#e10eb95eb57cdfe549bf29f97f1e4f1db679035c" @@ -4424,7 +4454,7 @@ ethereumjs-abi@0.6.5: bn.js "^4.10.0" ethereumjs-util "^4.3.0" -ethereumjs-abi@0.6.8: +ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.8: version "0.6.8" resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== @@ -5051,6 +5081,11 @@ for-in@^1.0.2: resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -6166,6 +6201,13 @@ is-function@^1.0.1: resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08" integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ== +is-generator-function@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" @@ -6197,6 +6239,14 @@ is-loopback-addr@^1.0.0: resolved "https://registry.yarnpkg.com/is-loopback-addr/-/is-loopback-addr-1.0.1.tgz#d4adf50d12d53100da62a397c61d6c83fe40aab9" integrity sha512-DhWU/kqY7X2F6KrrVTu7mHlbd2Pbo4D1YkAzasBMjQs6lJAoefxaA6m6CpSX0K6pjt9D0b9PNFI5zduy/vzOYw== +is-nan@^1.2.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" + integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + is-negative-zero@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" @@ -6308,6 +6358,17 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" +is-typed-array@^1.1.3, is-typed-array@^1.1.6: + version "1.1.7" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.7.tgz#881ddc660b13cb8423b2090fa88c0fe37a83eb2f" + integrity sha512-VxlpTBGknhQ3o7YiVjIhdLU6+oD8dPz/79vvvH4F+S/c8608UCVa9fgDpa1kZgFoUST2DCgacc70UszKgzKuvA== + dependencies: + available-typed-arrays "^1.0.4" + call-bind "^1.0.2" + es-abstract "^1.18.5" + foreach "^2.0.5" + has-tostringtag "^1.0.0" + is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -7851,9 +7912,9 @@ multibase@^0.7.0: buffer "^5.5.0" multibase@^4.0.1, multibase@^4.0.2: - version "4.0.4" - resolved "https://registry.yarnpkg.com/multibase/-/multibase-4.0.4.tgz#55ef53e6acce223c5a09341a8a3a3d973871a577" - integrity sha512-8/JmrdSGzlw6KTgAJCOqUBSGd1V6186i/X8dDCGy/lbCKrQ+1QB6f3HE+wPr7Tpdj4U3gutaj9jG2rNX6UpiJg== + version "4.0.5" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-4.0.5.tgz#620293b524e01f504b750cef585c2bdc6ee1c64c" + integrity sha512-oqFkOYXdUkakxT8MqGyn5sE1KYeVt1zataOTvg688skQp6TVBv9XnouCcVO86XKFzh/UTiCGmEImTx6ZnPZ0qQ== dependencies: "@multiformats/base-x" "^4.0.1" @@ -7955,11 +8016,16 @@ nano-json-stream-parser@^0.1.2: resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= -nanoid@3.1.23, nanoid@^3.0.2, nanoid@^3.1.20: +nanoid@3.1.23: version "3.1.23" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81" integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw== +nanoid@^3.0.2, nanoid@^3.1.20: + version "3.1.24" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.24.tgz#d7ac20215f595c26d314ee5671169a27b609025f" + integrity sha512-WNhqqgD4qH7TQdU9ujXfFa/hQI5rOGGnZq+JRmz4JwMZFCgSZVquTq3ORUSv6IC+Y41ACBYV8a8J1kPkqGIiQg== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -10794,7 +10860,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= -tweetnacl@^1.0.0: +tweetnacl@^1.0.0, tweetnacl@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== @@ -11066,6 +11132,18 @@ util.promisify@^1.0.0: has-symbols "^1.0.1" object.getownpropertydescriptors "^2.1.1" +util@^0.12.0: + version "0.12.4" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.4.tgz#66121a31420df8f01ca0c464be15dfa1d1850253" + integrity sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + safe-buffer "^5.1.2" + which-typed-array "^1.1.2" + utila@~0.4: version "0.4.0" resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" @@ -11662,6 +11740,18 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= +which-typed-array@^1.1.2: + version "1.1.6" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.6.tgz#f3713d801da0720a7f26f50c596980a9f5c8b383" + integrity sha512-DdY984dGD5sQ7Tf+x1CkXzdg85b9uEel6nr4UkFg1LoE9OXv3uRuZhe5CoWdawhGACeFpEZXH8fFLQnDhbpm/Q== + dependencies: + available-typed-arrays "^1.0.4" + call-bind "^1.0.2" + es-abstract "^1.18.5" + foreach "^2.0.5" + has-tostringtag "^1.0.0" + is-typed-array "^1.1.6" + which@2.0.2, which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"