From d1cf878ec976d0f94ab58d2747ae22f3941094c9 Mon Sep 17 00:00:00 2001 From: Dan Oved Date: Wed, 13 Sep 2023 15:08:22 -0700 Subject: [PATCH] added front-end helper to decode error result --- package/preminter.test.ts | 88 +++++++++++++++++++ package/preminter.ts | 20 ++++- .../ZoraCreator1155PremintExecutor.sol | 2 +- 3 files changed, 107 insertions(+), 3 deletions(-) diff --git a/package/preminter.test.ts b/package/preminter.test.ts index 100e46386..a5e870044 100644 --- a/package/preminter.test.ts +++ b/package/preminter.test.ts @@ -3,6 +3,8 @@ import { http, createWalletClient, createPublicClient, + BaseError, + ContractFunctionRevertedError, } from "viem"; import { foundry, zoraTestnet } from "viem/chains"; import { describe, it, beforeEach, expect } from "vitest"; @@ -24,6 +26,7 @@ import { ContractCreationConfig, PremintConfig, TokenCreationConfig, + decodeErc1155ErrorResult, preminterTypedDataDefinition, } from "./preminter"; @@ -295,6 +298,91 @@ describe("ZoraCreator1155Preminter", () => { 20 * 1000 ); + it.only("can decode the original erc1155 error from a premint error result", async ({ + zoraMintFee, + anvilChainId, + preminterAddress: preminterAddress, + fixedPriceMinterAddress, + }) => { + // setup contract and token creation parameters + const premintConfig = defaultPremintConfig(fixedPriceMinterAddress); + const contractConfig = defaultContractConfig({ + contractAdmin: creatorAccount, + }); + + // lets make it a random number to not break the existing tests that expect fresh data + premintConfig.uid = Math.round(Math.random() * 1000000); + + let contractAddress = await publicClient.readContract({ + abi: preminterAbi, + address: preminterAddress, + functionName: "getContractAddress", + args: [contractConfig], + }); + + // have creator sign the message to create the contract + // and the token + const signedMessage = await walletClient.signTypedData({ + ...preminterTypedDataDefinition({ + verifyingContract: contractAddress, + // we need to sign here for the anvil chain, cause thats where it is run on + chainId: anvilChainId, + premintConfig, + }), + account: creatorAccount, + }); + + const quantityToMint = 2n; + + const valueToSend = + (zoraMintFee + premintConfig.tokenConfig.pricePerToken) * quantityToMint; + + // send extra money, mint call should revert. + const wrongValueToSend = valueToSend + parseEther("1"); + + const comment = ""; + + await testClient.setBalance({ + address: collectorAccount, + value: parseEther("10"), + }); + + // get the premint status - it should not be minted + try { + const { result } = await publicClient.simulateContract({ + abi: preminterAbi, + functionName: "premint", + account: collectorAccount, + address: preminterAddress, + args: [ + contractConfig, + premintConfig, + signedMessage, + quantityToMint, + comment, + ], + value: wrongValueToSend, + }); + } catch (err) { + if (err instanceof BaseError) { + const revertError = err.walk( + (err) => err instanceof ContractFunctionRevertedError + ); + if (revertError instanceof ContractFunctionRevertedError) { + // do something with `errorName` + + const errorName = revertError.data!.errorName; + expect(errorName).toBe("Erc1155CallReverted"); + + const errorData = revertError.data!.args![0] as `0x${string}`; + + const decodedError = decodeErc1155ErrorResult(errorData); + + expect(decodedError.errorName).toBe("WrongValueSent"); + } + } + } + }); it( "can sign and mint multiple tokens", async ({ diff --git a/package/preminter.ts b/package/preminter.ts index 6b6f4e12c..4181ede10 100644 --- a/package/preminter.ts +++ b/package/preminter.ts @@ -1,7 +1,11 @@ import { Address } from "abitype"; import { ExtractAbiFunction, AbiParametersToPrimitiveTypes } from "abitype"; -import { zoraCreator1155PremintExecutorABI as preminterAbi } from "./wagmiGenerated"; -import { TypedDataDefinition } from "viem"; +import { + zoraCreator1155PremintExecutorABI as preminterAbi, + zoraCreator1155ImplABI, + zoraCreatorFixedPriceSaleStrategyABI, +} from "./wagmiGenerated"; +import { TypedDataDefinition, decodeErrorResult } from "viem"; type PremintInputs = ExtractAbiFunction< typeof preminterAbi, @@ -72,3 +76,15 @@ export const preminterTypedDataDefinition = ({ return result; }; + +export const decodeErc1155ErrorResult = (result: `0x${string}`) => { + const combinedAbi = [ + ...zoraCreator1155ImplABI.filter((x) => x.type === "error"), + ...zoraCreatorFixedPriceSaleStrategyABI.filter((x) => x.type === "error"), + ]; + + return decodeErrorResult({ + abi: combinedAbi, + data: result, + }); +}; diff --git a/src/premint/ZoraCreator1155PremintExecutor.sol b/src/premint/ZoraCreator1155PremintExecutor.sol index 157491b01..48f52af33 100644 --- a/src/premint/ZoraCreator1155PremintExecutor.sol +++ b/src/premint/ZoraCreator1155PremintExecutor.sol @@ -27,7 +27,7 @@ contract ZoraCreator1155PremintExecutor is Ownable2StepUpgradeable, UUPSUpgradea error MintNotYetStarted(); error InvalidSignature(); - error Erc1155CallReverted(bytes errorReverted); + error Erc1155CallReverted(bytes errorRevertedData); constructor(IZoraCreator1155Factory _factory) { zora1155Factory = _factory;