diff --git a/.changeset/young-pants-draw.md b/.changeset/young-pants-draw.md new file mode 100644 index 0000000000..ddb6a16d23 --- /dev/null +++ b/.changeset/young-pants-draw.md @@ -0,0 +1,5 @@ +--- +"viem": patch +--- + +Added `code` as a parameter to `call` + `readContract` – to enable Deployless Calls via Bytecode. diff --git a/package.json b/package.json index e1c8873177..3b3795f8cf 100644 --- a/package.json +++ b/package.json @@ -108,7 +108,7 @@ { "name": "viem (esm)", "path": "./src/_esm/index.js", - "limit": "59.6 kB", + "limit": "59.8 kB", "import": "*" }, { @@ -173,13 +173,13 @@ { "name": "viem/ens (tree-shaking)", "path": "./src/_esm/ens/index.js", - "limit": "22.3 kB", + "limit": "22.5 kB", "import": "{ getEnsAvatar }" }, { "name": "viem/siwe", "path": "./src/_esm/siwe/index.js", - "limit": "30.3 kB", + "limit": "30.5 kB", "import": "*" }, { diff --git a/site/pages/docs/actions/public/call.md b/site/pages/docs/actions/public/call.md index a12c1392b6..8b3e051c5f 100644 --- a/site/pages/docs/actions/public/call.md +++ b/site/pages/docs/actions/public/call.md @@ -40,17 +40,57 @@ export const publicClient = createPublicClient({ It is possible to call a function on a contract that has not been deployed yet. For instance, we may want to call a function on an [ERC-4337 Smart Account](https://eips.ethereum.org/EIPS/eip-4337) contract which has not been deployed. -Viem utilizes a **Deployless Call** pattern via a [Deploy Factory](https://docs.alchemy.com/docs/create2-an-alternative-to-deriving-contract-addresses#create2-contract-factory) to: -1. "temporarily deploy" a contract (e.g. a Smart Account) with a provided [Deployment Factory Contract](https://docs.alchemy.com/docs/create2-an-alternative-to-deriving-contract-addresses#create2-contract-factory) address ([`factory`](#factory-optional)) with deployment arguments ([`factoryData`](#factorydata-optional)), -2. Call the function on the "temporarily deployed" contract ([`to`](#to-optional)). +Viem offers two ways of performing a Deployless Call, via: -The example below demonstrates how we can utilize this pattern to call the `entryPoint` function on an [ERC-4337 Smart Account](https://eips.ethereum.org/EIPS/eip-4337) which has not been deployed: +- [Bytecode](#bytecode) +- a [Deploy Factory](#deploy-factory): "temporarily deploys" a contract with a provided [Deploy Factory](https://docs.alchemy.com/docs/create2-an-alternative-to-deriving-contract-addresses#create2-contract-factory), and calls the function on the deployed contract. + +:::tip +The **Deployless Call** patterns are also accessible via the [`readContract`](/docs/contract/readContract#deployless-reads) & [Contract Instance](/docs/contract/getContract) APIs. +::: + +#### Bytecode + +The example below demonstrates how we can utilize a Deployless Call **via Bytecode** to call the `name` function on the [Wagmi Example ERC721 contract](https://etherscan.io/address/0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2#code) which has not been deployed: :::code-group ```ts twoslash [example.ts] import { encodeFunctionData, parseAbi } from 'viem' -import { account, publicClient } from './config' +import { publicClient } from './config' + +const data = await publicClient.call({ + // Bytecode of the contract. Accessible here: https://etherscan.io/address/0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2#code + code: '0x...' + // Function to call on the contract. + data: encodeFunctionData({ + abi: parseAbi(['function name() view returns (string)']), + functionName: 'name' + }), +}) +``` + +```ts twoslash [config.ts] filename="config.ts" +import { createPublicClient, http } from 'viem' +import { mainnet } from 'viem/chains' + +export const publicClient = createPublicClient({ + chain: mainnet, + transport: http() +}) +``` + +::: + +#### Deploy Factory + +The example below demonstrates how we can utilize a Deployless Call **via a [Deploy Factory](https://docs.alchemy.com/docs/create2-an-alternative-to-deriving-contract-addresses#create2-contract-factory)** to call the `entryPoint` function on an [ERC-4337 Smart Account](https://eips.ethereum.org/EIPS/eip-4337) which has not been deployed: + +:::code-group + +```ts twoslash [example.ts] +import { encodeFunctionData, parseAbi } from 'viem' +import { owner, publicClient } from './config' const data = await publicClient.call({ // Address of the contract deployer (e.g. Smart Account Factory). @@ -60,7 +100,7 @@ const data = await publicClient.call({ factoryData: encodeFunctionData({ abi: parseAbi(['function createAccount(address owner, uint256 salt)']), functionName: 'createAccount', - args: [account, 0n], + args: [owner, 0n], }), // Function to call on the contract (e.g. Smart Account contract). @@ -78,7 +118,7 @@ const data = await publicClient.call({ import { createPublicClient, http } from 'viem' import { mainnet } from 'viem/chains' -export const account = '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266' +export const owner = '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266' export const publicClient = createPublicClient({ chain: mainnet, @@ -92,10 +132,6 @@ export const publicClient = createPublicClient({ This example utilizes the [SimpleAccountFactory](https://github.com/eth-infinitism/account-abstraction/blob/develop/contracts/samples/SimpleAccountFactory.sol). ::: -:::tip -The **Deployless Call** pattern (and `factory` + `factoryData` parameters) is also accessible via the [`readContract`](/docs/contract/readContract#deployless-reads) & [Contract Instance](http://localhost:5173/docs/contract/getContract) APIs. -::: - ## Returns `0x${string}` @@ -211,6 +247,21 @@ const data = await publicClient.call({ }) ``` +### code (optional) + +- **Type:** + +Bytecode to perform the call against. + +```ts twoslash +// [!include ~/snippets/publicClient.ts] +// ---cut--- +const data = await publicClient.call({ + code: '0x...', // [!code focus] + data: '0xdeadbeef', +}) +``` + ### factory (optional) - **Type:** diff --git a/site/pages/docs/contract/readContract.md b/site/pages/docs/contract/readContract.md index b6bd6f2da9..b108fc4f04 100644 --- a/site/pages/docs/contract/readContract.md +++ b/site/pages/docs/contract/readContract.md @@ -107,11 +107,47 @@ export const publicClient = createPublicClient({ It is possible to call a function on a contract that has not been deployed yet. For instance, we may want to call a function on an [ERC-4337 Smart Account](https://eips.ethereum.org/EIPS/eip-4337) contract which has not been deployed. -Viem utilizes a **Deployless Read** pattern via a [Deploy Factory](https://docs.alchemy.com/docs/create2-an-alternative-to-deriving-contract-addresses#create2-contract-factory) to: -1. "temporarily deploy" a contract (e.g. a Smart Account) with a provided [Deployment Factory Contract](https://docs.alchemy.com/docs/create2-an-alternative-to-deriving-contract-addresses#create2-contract-factory) address ([`factory`](#factory-optional)) with deployment arguments ([`factoryData`](#factorydata-optional)), -2. Call the function on the "temporarily deployed" contract ([`address`](#address)). +Viem offers two ways of performing a Deployless Call, via: -The example below demonstrates how we can utilize this pattern to call the `entryPoint` function on an [ERC-4337 Smart Account](https://eips.ethereum.org/EIPS/eip-4337) which has not been deployed: +- [Bytecode](#bytecode) +- a [Deploy Factory](#deploy-factory): "temporarily deploys" a contract with a provided [Deploy Factory](https://docs.alchemy.com/docs/create2-an-alternative-to-deriving-contract-addresses#create2-contract-factory), and calls the function on the deployed contract. + +:::tip +The **Deployless Call** patterns are also accessible via the [`readContract`](/docs/contract/readContract#deployless-reads) & [Contract Instance](/docs/contract/getContract) APIs. +::: + +#### Bytecode + +The example below demonstrates how we can utilize a Deployless Call **via Bytecode** to call the `name` function on the [Wagmi Example ERC721 contract](https://etherscan.io/address/0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2#code) which has not been deployed: + +:::code-group + +```ts twoslash [example.ts] +import { parseAbi } from 'viem' +import { publicClient } from './config' + +const data = await publicClient.readContract({ + abi: parseAbi(['function name() view returns (string)']), + code: '0x...', // Accessible here: https://etherscan.io/address/0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2#code + functionName: 'name' +}) +``` + +```ts twoslash [config.ts] filename="config.ts" +import { createPublicClient, http } from 'viem' +import { mainnet } from 'viem/chains' + +export const publicClient = createPublicClient({ + chain: mainnet, + transport: http() +}) +``` + +::: + +#### Deploy Factory + +The example below demonstrates how we can utilize a Deployless Call **via a [Deploy Factory](https://docs.alchemy.com/docs/create2-an-alternative-to-deriving-contract-addresses#create2-contract-factory)** to call the `entryPoint` function on an [ERC-4337 Smart Account](https://eips.ethereum.org/EIPS/eip-4337) which has not been deployed: :::code-group diff --git a/src/actions/public/call.test.ts b/src/actions/public/call.test.ts index 3bf6953f2c..35c971017e 100644 --- a/src/actions/public/call.test.ts +++ b/src/actions/public/call.test.ts @@ -5,7 +5,11 @@ import { Mock4337AccountFactory, OffchainLookupExample, } from '~test/contracts/generated.js' -import { baycContractConfig, usdcContractConfig } from '~test/src/abis.js' +import { + baycContractConfig, + usdcContractConfig, + wagmiContractConfig, +} from '~test/src/abis.js' import { createCcipServer } from '~test/src/ccip.js' import { accounts } from '~test/src/constants.js' import { blobData, kzg } from '~test/src/kzg.js' @@ -30,6 +34,7 @@ import { createClient, decodeFunctionResult, encodeAbiParameters, + multicall3Abi, pad, parseEther, stringToHex, @@ -1006,8 +1011,8 @@ describe('batch call', () => { }) }) -describe('deployless counterfactual call', () => { - test('call to account that has not been deployed', async () => { +describe('deployless call (factory)', () => { + test('default', async () => { const { factoryAddress } = await deployMock4337Account() const address = await readContract(client, { @@ -1077,6 +1082,78 @@ describe('deployless counterfactual call', () => { }) }) +describe('deployless call (bytecode)', () => { + test('default', async () => { + const { data } = await call(client, { + code: wagmiContractConfig.bytecode, + data: encodeFunctionData({ + abi: wagmiContractConfig.abi, + functionName: 'name', + }), + }) + + expect( + decodeFunctionResult({ + abi: wagmiContractConfig.abi, + data: data!, + functionName: 'name', + }), + ).toMatchInlineSnapshot(`"wagmi"`) + }) + + test('multicall', async () => { + const code = + '0x608060405234801561001057600080fd5b50610ee0806100206000396000f3fe6080604052600436106100f35760003560e01c80634d2301cc1161008a578063a8b0574e11610059578063a8b0574e1461025a578063bce38bd714610275578063c3077fa914610288578063ee82ac5e1461029b57600080fd5b80634d2301cc146101ec57806372425d9d1461022157806382ad56cb1461023457806386d516e81461024757600080fd5b80633408e470116100c65780633408e47014610191578063399542e9146101a45780633e64a696146101c657806342cbb15c146101d957600080fd5b80630f28c97d146100f8578063174dea711461011a578063252dba421461013a57806327e86d6e1461015b575b600080fd5b34801561010457600080fd5b50425b6040519081526020015b60405180910390f35b61012d610128366004610a85565b6102ba565b6040516101119190610bbe565b61014d610148366004610a85565b6104ef565b604051610111929190610bd8565b34801561016757600080fd5b50437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0140610107565b34801561019d57600080fd5b5046610107565b6101b76101b2366004610c60565b610690565b60405161011193929190610cba565b3480156101d257600080fd5b5048610107565b3480156101e557600080fd5b5043610107565b3480156101f857600080fd5b50610107610207366004610ce2565b73ffffffffffffffffffffffffffffffffffffffff163190565b34801561022d57600080fd5b5044610107565b61012d610242366004610a85565b6106ab565b34801561025357600080fd5b5045610107565b34801561026657600080fd5b50604051418152602001610111565b61012d610283366004610c60565b61085a565b6101b7610296366004610a85565b610a1a565b3480156102a757600080fd5b506101076102b6366004610d18565b4090565b60606000828067ffffffffffffffff8111156102d8576102d8610d31565b60405190808252806020026020018201604052801561031e57816020015b6040805180820190915260008152606060208201528152602001906001900390816102f65790505b5092503660005b8281101561047757600085828151811061034157610341610d60565b6020026020010151905087878381811061035d5761035d610d60565b905060200281019061036f9190610d8f565b6040810135958601959093506103886020850185610ce2565b73ffffffffffffffffffffffffffffffffffffffff16816103ac6060870187610dcd565b6040516103ba929190610e32565b60006040518083038185875af1925050503d80600081146103f7576040519150601f19603f3d011682016040523d82523d6000602084013e6103fc565b606091505b50602080850191909152901515808452908501351761046d577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260846000fd5b5050600101610325565b508234146104e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d756c746963616c6c333a2076616c7565206d69736d6174636800000000000060448201526064015b60405180910390fd5b50505092915050565b436060828067ffffffffffffffff81111561050c5761050c610d31565b60405190808252806020026020018201604052801561053f57816020015b606081526020019060019003908161052a5790505b5091503660005b8281101561068657600087878381811061056257610562610d60565b90506020028101906105749190610e42565b92506105836020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166105a66020850185610dcd565b6040516105b4929190610e32565b6000604051808303816000865af19150503d80600081146105f1576040519150601f19603f3d011682016040523d82523d6000602084013e6105f6565b606091505b5086848151811061060957610609610d60565b602090810291909101015290508061067d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b50600101610546565b5050509250929050565b43804060606106a086868661085a565b905093509350939050565b6060818067ffffffffffffffff8111156106c7576106c7610d31565b60405190808252806020026020018201604052801561070d57816020015b6040805180820190915260008152606060208201528152602001906001900390816106e55790505b5091503660005b828110156104e657600084828151811061073057610730610d60565b6020026020010151905086868381811061074c5761074c610d60565b905060200281019061075e9190610e76565b925061076d6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166107906040850185610dcd565b60405161079e929190610e32565b6000604051808303816000865af19150503d80600081146107db576040519150601f19603f3d011682016040523d82523d6000602084013e6107e0565b606091505b506020808401919091529015158083529084013517610851577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260646000fd5b50600101610714565b6060818067ffffffffffffffff81111561087657610876610d31565b6040519080825280602002602001820160405280156108bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816108945790505b5091503660005b82811015610a105760008482815181106108df576108df610d60565b602002602001015190508686838181106108fb576108fb610d60565b905060200281019061090d9190610e42565b925061091c6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff1661093f6020850185610dcd565b60405161094d929190610e32565b6000604051808303816000865af19150503d806000811461098a576040519150601f19603f3d011682016040523d82523d6000602084013e61098f565b606091505b506020830152151581528715610a07578051610a07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b506001016108c3565b5050509392505050565b6000806060610a2b60018686610690565b919790965090945092505050565b60008083601f840112610a4b57600080fd5b50813567ffffffffffffffff811115610a6357600080fd5b6020830191508360208260051b8501011115610a7e57600080fd5b9250929050565b60008060208385031215610a9857600080fd5b823567ffffffffffffffff811115610aaf57600080fd5b610abb85828601610a39565b90969095509350505050565b6000815180845260005b81811015610aed57602081850181015186830182015201610ad1565b81811115610aff576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b84811015610bb1578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051151584528401516040858501819052610b9d81860183610ac7565b9a86019a9450505090830190600101610b4f565b5090979650505050505050565b602081526000610bd16020830184610b32565b9392505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610c52577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018452610c40868351610ac7565b95509284019290840190600101610c06565b509398975050505050505050565b600080600060408486031215610c7557600080fd5b83358015158114610c8557600080fd5b9250602084013567ffffffffffffffff811115610ca157600080fd5b610cad86828701610a39565b9497909650939450505050565b838152826020820152606060408201526000610cd96060830184610b32565b95945050505050565b600060208284031215610cf457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610bd157600080fd5b600060208284031215610d2a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112610dc357600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610e0257600080fd5b83018035915067ffffffffffffffff821115610e1d57600080fd5b602001915036819003821315610a7e57600080fd5b8183823760009101908152919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610dc357600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112610dc357600080fdfea2646970667358221220bb2b5c71a328032f97c676ae39a1ec2148d3e5d6f73d95e9b17910152d61f16264736f6c634300080c0033' + + const { data } = await call(client, { + code, + data: encodeFunctionData({ + abi: multicall3Abi, + functionName: 'aggregate3', + args: [ + [ + { + target: wagmiContractConfig.address, + allowFailure: true, + callData: encodeFunctionData({ + abi: wagmiContractConfig.abi, + functionName: 'name', + }), + }, + { + target: wagmiContractConfig.address, + allowFailure: true, + callData: encodeFunctionData({ + abi: wagmiContractConfig.abi, + functionName: 'totalSupply', + }), + }, + ], + ], + }), + }) + + expect( + decodeFunctionResult({ + abi: multicall3Abi, + data: data!, + functionName: 'aggregate3', + }), + ).toMatchInlineSnapshot(` + [ + { + "returnData": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000057761676d69000000000000000000000000000000000000000000000000000000", + "success": true, + }, + { + "returnData": "0x0000000000000000000000000000000000000000000000000000000000000277", + "success": true, + }, + ] + `) + }) +}) + describe('getRevertErrorData', () => { test('default', () => { expect(getRevertErrorData(new Error('lol'))).toBe(undefined) diff --git a/src/actions/public/call.ts b/src/actions/public/call.ts index 99aca62b0c..77151500f7 100644 --- a/src/actions/public/call.ts +++ b/src/actions/public/call.ts @@ -9,7 +9,10 @@ import type { Client } from '../../clients/createClient.js' import type { Transport } from '../../clients/transports/createTransport.js' import { multicall3Abi } from '../../constants/abis.js' import { aggregate3Signature } from '../../constants/contract.js' -import { counterfactualContractCallByteCode } from '../../constants/contracts.js' +import { + deploylessCallViaBytecodeBytecode, + deploylessCallViaFactoryBytecode, +} from '../../constants/contracts.js' import { BaseError } from '../../errors/base.js' import { ChainDoesNotSupportContract, @@ -76,12 +79,17 @@ import type { export type CallParameters< TChain extends Chain | undefined = Chain | undefined, > = UnionOmit, 'from'> & { + /** Account attached to the call (msg.sender). */ account?: Account | Address | undefined + /** Whether or not to enable multicall batching on this call. */ batch?: boolean | undefined + /** Bytecode to perform the call on. */ + code?: Hex | undefined /** Contract deployment factory address (ie. Create2 factory, Smart Account factory, etc). */ factory?: Address | undefined /** Calldata to execute on the factory to deploy the contract. */ factoryData?: Hex | undefined + /** State overrides for the call. */ stateOverride?: StateOverride | undefined } & ( | { @@ -111,7 +119,8 @@ export type CallErrorType = GetCallErrorReturnType< | FormatTransactionRequestErrorType | ScheduleMulticallErrorType | RequestErrorType - | ToCounterfactualDataErrorType + | ToDeploylessCallViaBytecodeDataErrorType + | ToDeploylessCallViaFactoryDataErrorType > /** @@ -150,6 +159,7 @@ export async function call( blockTag = 'latest', accessList, blobs, + code, data: data_, factory, factoryData, @@ -166,14 +176,25 @@ export async function call( } = args const account = account_ ? parseAccount(account_) : undefined - // Check if the call is going to be routed via a counterfactual contract deployment. - const counterfactual = factory && factoryData && to && data_ + // Check if the call is deployless via bytecode. + const deploylessCallViaBytecode = code && data_ + // Check if the call is deployless via a factory. + const deploylessCallViaFactory = factory && factoryData && to && data_ + const deploylessCall = deploylessCallViaBytecode || deploylessCallViaFactory + const data = (() => { - // If the call is going to be routed via a counterfactual contract deployment, - // we need to get the data to deploy the counterfactual contract, and then perform - // the call. - if (counterfactual) - return toCounterfactualData({ data: data_, factory, factoryData, to }) + if (deploylessCallViaBytecode) + return toDeploylessCallViaBytecodeData({ + code, + data: data_, + }) + if (deploylessCallViaFactory) + return toDeploylessCallViaFactoryData({ + data: data_, + factory, + factoryData, + to, + }) return data_ })() @@ -201,7 +222,7 @@ export async function call( maxFeePerGas, maxPriorityFeePerGas, nonce, - to: counterfactual ? undefined : to, + to: deploylessCall ? undefined : to, value, } as TransactionRequest) as TransactionRequest @@ -248,7 +269,7 @@ export async function call( return { data: await offchainLookup(client, { data, to }) } // Check for counterfactual deployment error. - if (counterfactual && data?.slice(0, 10) === '0x101bb98d') + if (deploylessCall && data?.slice(0, 10) === '0x101bb98d') throw new CounterfactualDeploymentFailedError({ factory }) throw getCallError(err as ErrorType, { @@ -374,9 +395,27 @@ async function scheduleMulticall( return { data: returnData } } -type ToCounterfactualDataErrorType = EncodeDeployDataErrorType | ErrorType +type ToDeploylessCallViaBytecodeDataErrorType = + | EncodeDeployDataErrorType + | ErrorType + +function toDeploylessCallViaBytecodeData(parameters: { + code: Hex + data: Hex +}) { + const { code, data } = parameters + return encodeDeployData({ + abi: parseAbi(['constructor(bytes, bytes)']), + bytecode: deploylessCallViaBytecodeBytecode, + args: [code, data], + }) +} + +type ToDeploylessCallViaFactoryDataErrorType = + | EncodeDeployDataErrorType + | ErrorType -function toCounterfactualData(parameters: { +function toDeploylessCallViaFactoryData(parameters: { data: Hex factory: Address factoryData: Hex @@ -384,11 +423,8 @@ function toCounterfactualData(parameters: { }) { const { data, factory, factoryData, to } = parameters return encodeDeployData({ - abi: parseAbi([ - 'error CounterfactualDeployFailed(bytes)', - 'constructor(address, bytes, address, bytes)', - ]), - bytecode: counterfactualContractCallByteCode, + abi: parseAbi(['constructor(address, bytes, address, bytes)']), + bytecode: deploylessCallViaFactoryBytecode, args: [to, data, factory, factoryData], }) } diff --git a/src/actions/public/readContract.test.ts b/src/actions/public/readContract.test.ts index 2660b50c6e..3ad821f005 100644 --- a/src/actions/public/readContract.test.ts +++ b/src/actions/public/readContract.test.ts @@ -195,7 +195,7 @@ describe('bayc', () => { }) }) -describe('counterfactual read', () => { +describe('deployless read (factory)', () => { test('default', async () => { const { factoryAddress: factory } = await deployMock4337Account() @@ -233,6 +233,17 @@ describe('counterfactual read', () => { }) }) +describe('deployless read (bytecode)', () => { + test('default', async () => { + const result = await readContract(client, { + abi: wagmiContractConfig.abi, + code: wagmiContractConfig.bytecode, + functionName: 'name', + }) + expect(result).toMatchInlineSnapshot(`"wagmi"`) + }) +}) + describe('contract errors', () => { test('revert', async () => { const { contractAddress } = await deployErrorExample() diff --git a/src/actions/public/readContract.ts b/src/actions/public/readContract.ts index 1203530915..22c3423183 100644 --- a/src/actions/public/readContract.ts +++ b/src/actions/public/readContract.ts @@ -50,7 +50,7 @@ export type ReadContractParameters< | 'stateOverride' > > & - ContractFunctionParameters + ContractFunctionParameters export type ReadContractReturnType< abi extends Abi | readonly unknown[] = Abi, @@ -124,7 +124,7 @@ export async function readContract< )({ ...(rest as CallParameters), data: calldata, - to: address, + to: address!, }) return decodeFunctionResult({ abi, diff --git a/src/actions/public/simulateContract.test.ts b/src/actions/public/simulateContract.test.ts index fda7c02234..42b62bb829 100644 --- a/src/actions/public/simulateContract.test.ts +++ b/src/actions/public/simulateContract.test.ts @@ -175,7 +175,8 @@ describe('wagmi', () => { test('args: dataSuffix', async () => { const spy = vi.spyOn(client, 'call') const { request } = await simulateContract(client, { - ...wagmiContractConfig, + abi: wagmiContractConfig.abi, + address: wagmiContractConfig.address, account: accounts[0].address, functionName: 'mint', dataSuffix: '0x12345678', diff --git a/src/actions/public/simulateContract.ts b/src/actions/public/simulateContract.ts index 765e86d746..42b43444fc 100644 --- a/src/actions/public/simulateContract.ts +++ b/src/actions/public/simulateContract.ts @@ -66,7 +66,14 @@ export type SimulateContractParameters< > & UnionOmit< CallParameters, - 'account' | 'batch' | 'to' | 'data' | 'factory' | 'factoryData' | 'value' + | 'account' + | 'batch' + | 'code' + | 'to' + | 'data' + | 'factory' + | 'factoryData' + | 'value' > & GetValue< abi, diff --git a/src/actions/wallet/writeContract.test.ts b/src/actions/wallet/writeContract.test.ts index aed17afbc0..410c1ebabd 100644 --- a/src/actions/wallet/writeContract.test.ts +++ b/src/actions/wallet/writeContract.test.ts @@ -133,7 +133,8 @@ describe('args: chain', () => { test('args: dataSuffix', async () => { const spy = vi.spyOn(client, 'sendTransaction') await writeContract(client, { - ...wagmiContractConfig, + abi: wagmiContractConfig.abi, + address: wagmiContractConfig.address, account: accounts[0].address, functionName: 'mint', dataSuffix: '0x12345678', diff --git a/src/actions/wallet/writeContract.ts b/src/actions/wallet/writeContract.ts index 8fa96987d2..5231f770cc 100644 --- a/src/actions/wallet/writeContract.ts +++ b/src/actions/wallet/writeContract.ts @@ -53,6 +53,7 @@ export type WriteContractParameters< 'nonpayable' | 'payable', functionName, args, + false, allFunctionNames > & GetChainParameter & diff --git a/src/constants/contracts.ts b/src/constants/contracts.ts index 0271330899..64c9539671 100644 --- a/src/constants/contracts.ts +++ b/src/constants/contracts.ts @@ -1,4 +1,7 @@ -export const counterfactualContractCallByteCode = +export const deploylessCallViaBytecodeBytecode = + '0x608060405234801561001057600080fd5b5060405161018e38038061018e83398101604081905261002f91610124565b6000808351602085016000f59050803b61004857600080fd5b6000808351602085016000855af16040513d6000823e81610067573d81fd5b3d81f35b634e487b7160e01b600052604160045260246000fd5b600082601f83011261009257600080fd5b81516001600160401b038111156100ab576100ab61006b565b604051601f8201601f19908116603f011681016001600160401b03811182821017156100d9576100d961006b565b6040528181528382016020018510156100f157600080fd5b60005b82811015610110576020818601810151838301820152016100f4565b506000918101602001919091529392505050565b6000806040838503121561013757600080fd5b82516001600160401b0381111561014d57600080fd5b61015985828601610081565b602085015190935090506001600160401b0381111561017757600080fd5b61018385828601610081565b915050925092905056fe' + +export const deploylessCallViaFactoryBytecode = '0x608060405234801561001057600080fd5b506040516102c03803806102c083398101604081905261002f916101e6565b836001600160a01b03163b6000036100e457600080836001600160a01b03168360405161005c9190610270565b6000604051808303816000865af19150503d8060008114610099576040519150601f19603f3d011682016040523d82523d6000602084013e61009e565b606091505b50915091508115806100b857506001600160a01b0386163b155b156100e1578060405163101bb98d60e01b81526004016100d8919061028c565b60405180910390fd5b50505b6000808451602086016000885af16040513d6000823e81610103573d81fd5b3d81f35b80516001600160a01b038116811461011e57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561015457818101518382015260200161013c565b50506000910152565b600082601f83011261016e57600080fd5b81516001600160401b0381111561018757610187610123565b604051601f8201601f19908116603f011681016001600160401b03811182821017156101b5576101b5610123565b6040528181528382016020018510156101cd57600080fd5b6101de826020830160208701610139565b949350505050565b600080600080608085870312156101fc57600080fd5b61020585610107565b60208601519094506001600160401b0381111561022157600080fd5b61022d8782880161015d565b93505061023c60408601610107565b60608601519092506001600160401b0381111561025857600080fd5b6102648782880161015d565b91505092959194509250565b60008251610282818460208701610139565b9190910192915050565b60208152600082518060208401526102ab816040850160208701610139565b601f01601f1916919091016040019291505056fe' export const universalSignatureValidatorByteCode = diff --git a/src/errors/contract.ts b/src/errors/contract.ts index 7d7a781692..17503bf0b2 100644 --- a/src/errors/contract.ts +++ b/src/errors/contract.ts @@ -284,9 +284,11 @@ export type CounterfactualDeploymentFailedErrorType = } export class CounterfactualDeploymentFailedError extends BaseError { override name = 'CounterfactualDeploymentFailedError' - constructor({ factory }: { factory: Address }) { + constructor({ factory }: { factory?: Address | undefined }) { super( - `Deployment for counterfactual contract call failed for factory "${factory}".`, + `Deployment for counterfactual contract call failed${ + factory ? ` for factory "${factory}".` : '' + }`, { metaMessages: [ 'Please ensure:', diff --git a/src/types/contract.ts b/src/types/contract.ts index 9dc276df54..6a1ba2774a 100644 --- a/src/types/contract.ts +++ b/src/types/contract.ts @@ -197,19 +197,22 @@ export type ContractFunctionParameters< mutability, functionName > = ContractFunctionArgs, + deployless extends boolean = false, /// allFunctionNames = ContractFunctionName, allArgs = ContractFunctionArgs, // when `args` is inferred to `readonly []` ("inputs": []) or `never` (`abi` declared as `Abi` or not inferrable), allow `args` to be optional. // important that both branches return same structural type > = { - address: Address abi: abi functionName: | allFunctionNames // show all options | (functionName extends allFunctionNames ? functionName : never) // infer value args?: (abi extends Abi ? UnionWiden : never) | allArgs | undefined -} & (readonly [] extends allArgs ? {} : { args: Widen }) +} & (readonly [] extends allArgs ? {} : { args: Widen }) & + (deployless extends true + ? { address?: undefined; code: Hex } + : { address: Address }) export type ContractFunctionReturnType< abi extends Abi | readonly unknown[] = Abi, diff --git a/test/contracts/src/DeploylessCallViaBytecode.sol b/test/contracts/src/DeploylessCallViaBytecode.sol new file mode 100644 index 0000000000..1c5d742a71 --- /dev/null +++ b/test/contracts/src/DeploylessCallViaBytecode.sol @@ -0,0 +1,28 @@ +pragma solidity ^0.8.17; + +// SPDX-License-Identifier: UNLICENSED + +contract DeploylessCallViaBytecode { + constructor( + bytes memory bytecode, + bytes memory data + ) { + address to; + assembly { + to := create2(0, add(bytecode, 0x20), mload(bytecode), 0) + if iszero(extcodesize(to)) { + revert(0, 0) + } + } + + assembly { + let success := call(gas(), to, 0, add(data, 0x20), mload(data), 0, 0) + let ptr := mload(0x40) + returndatacopy(ptr, 0, returndatasize()) + if iszero(success) { + revert(ptr, returndatasize()) + } + return(ptr, returndatasize()) + } + } +} \ No newline at end of file diff --git a/test/src/abis.ts b/test/src/abis.ts index 62e71f0da4..9c402b0fa6 100644 --- a/test/src/abis.ts +++ b/test/src/abis.ts @@ -1466,6 +1466,8 @@ export const wagmiContractConfig = { type: 'function', }, ], + bytecode: + '0x608060405260006007553480156200001657600080fd5b50604051806040016040528060058152602001647761676d6960d81b815250604051806040016040528060058152602001645741474d4960d81b81525081600090805190602001906200006b9291906200008a565b508051620000819060019060208401906200008a565b5050506200016c565b828054620000989062000130565b90600052602060002090601f016020900481019282620000bc576000855562000107565b82601f10620000d757805160ff191683800117855562000107565b8280016001018555821562000107579182015b8281111562000107578251825591602001919060010190620000ea565b506200011592915062000119565b5090565b5b808211156200011557600081556001016200011a565b600181811c908216806200014557607f821691505b6020821081036200016657634e487b7160e01b600052602260045260246000fd5b50919050565b6128c2806200017c6000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c80636352211e11610097578063a22cb46511610066578063a22cb46514610215578063b88d4fde14610228578063c87b56dd1461023b578063e985e9c51461024e57600080fd5b80636352211e146101d457806370a08231146101e757806395d89b41146101fa578063a0712d681461020257600080fd5b80631249c58b116100d35780631249c58b1461018f57806318160ddd1461019757806323b872dd146101ae57806342842e0e146101c157600080fd5b806301ffc9a71461010557806306fdde031461012d578063081812fc14610142578063095ea7b31461017a575b600080fd5b61011861011336600461178f565b610297565b60405190151581526020015b60405180910390f35b61013561037c565b6040516101249190611829565b61015561015036600461183c565b61040e565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610124565b61018d61018836600461187e565b6104d3565b005b61018d61062b565b6101a060065481565b604051908152602001610124565b61018d6101bc3660046118a8565b61067d565b61018d6101cf3660046118a8565b610704565b6101556101e236600461183c565b61071f565b6101a06101f53660046118e4565b6107b7565b61013561086b565b61018d61021036600461183c565b61087a565b61018d6102233660046118ff565b610902565b61018d61023636600461196a565b610911565b61013561024936600461183c565b61099f565b61011861025c366004611a64565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260056020908152604080832093909416825291909152205460ff1690565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd00000000000000000000000000000000000000000000000000000000148061032a57507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061037657507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b60606000805461038b90611a97565b80601f01602080910402602001604051908101604052809291908181526020018280546103b790611a97565b80156104045780601f106103d957610100808354040283529160200191610404565b820191906000526020600020905b8154815290600101906020018083116103e757829003601f168201915b5050505050905090565b60008181526002602052604081205473ffffffffffffffffffffffffffffffffffffffff166104aa5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e000000000000000000000000000000000000000060648201526084015b60405180910390fd5b5060009081526004602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b60006104de8261071f565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036105815760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f720000000000000000000000000000000000000000000000000000000000000060648201526084016104a1565b3373ffffffffffffffffffffffffffffffffffffffff821614806105aa57506105aa813361025c565b61061c5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c000000000000000060648201526084016104a1565b6106268383610b07565b505050565b6007545b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff16156106615760010161062f565b61066b3382610ba7565b60068054600190810190915501600755565b6106873382610bc1565b6106f95760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f76656400000000000000000000000000000060648201526084016104a1565b610626838383610d17565b61062683838360405180602001604052806000815250610911565b60008181526002602052604081205473ffffffffffffffffffffffffffffffffffffffff16806103765760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201527f656e7420746f6b656e000000000000000000000000000000000000000000000060648201526084016104a1565b600073ffffffffffffffffffffffffffffffffffffffff82166108425760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560448201527f726f20616464726573730000000000000000000000000000000000000000000060648201526084016104a1565b5073ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205490565b60606001805461038b90611a97565b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff16156108ec5760405162461bcd60e51b815260206004820152601160248201527f546f6b656e2049442069732074616b656e00000000000000000000000000000060448201526064016104a1565b6108f63382610ba7565b50600680546001019055565b61090d338383610f4a565b5050565b61091b3383610bc1565b61098d5760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f76656400000000000000000000000000000060648201526084016104a1565b6109998484848461105d565b50505050565b6040517f666f726567726f756e64000000000000000000000000000000000000000000006020820152602a810182905260609060009061016890604a016040516020818303038152906040528051906020012060001c6109ff9190611b19565b6040517f6261636b67726f756e64000000000000000000000000000000000000000000006020820152602a810185905290915060009061016890604a016040516020818303038152906040528051906020012060001c610a5f9190611b19565b90506000610aba610a6f866110e6565b610aa9610a7b866110e6565b610a84866110e6565b604051602001610a95929190611b2d565b60405160208183030381529060405261121b565b604051602001610a959291906125ba565b9050600081604051602001610acf919061268b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529695505050505050565b600081815260046020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84169081179091558190610b618261071f565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b61090d82826040518060200160405280600081525061136e565b60008181526002602052604081205473ffffffffffffffffffffffffffffffffffffffff16610c585760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e000000000000000000000000000000000000000060648201526084016104a1565b6000610c638361071f565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480610cd1575073ffffffffffffffffffffffffffffffffffffffff80821660009081526005602090815260408083209388168352929052205460ff165b80610d0f57508373ffffffffffffffffffffffffffffffffffffffff16610cf78461040e565b73ffffffffffffffffffffffffffffffffffffffff16145b949350505050565b8273ffffffffffffffffffffffffffffffffffffffff16610d378261071f565b73ffffffffffffffffffffffffffffffffffffffff1614610dc05760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e657200000000000000000000000000000000000000000000000000000060648201526084016104a1565b73ffffffffffffffffffffffffffffffffffffffff8216610e485760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016104a1565b610e53600082610b07565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120805460019290610e899084906126ff565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260408120805460019290610ec4908490612716565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fc55760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c65720000000000000060448201526064016104a1565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526005602090815260408083209487168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b611068848484610d17565b611074848484846113f7565b6109995760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e746572000000000000000000000000000060648201526084016104a1565b60608160000361112957505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611153578061113d8161272e565b915061114c9050600a83612766565b915061112d565b60008167ffffffffffffffff81111561116e5761116e61193b565b6040519080825280601f01601f191660200182016040528015611198576020820181803683370190505b5090505b8415610d0f576111ad6001836126ff565b91506111ba600a86611b19565b6111c5906030612716565b60f81b8183815181106111da576111da61277a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611214600a86612766565b945061119c565b6060815160000361123a57505060408051602081019091526000815290565b600060405180606001604052806040815260200161284d60409139905060006003845160026112699190612716565b6112739190612766565b61127e9060046127a9565b67ffffffffffffffff8111156112965761129661193b565b6040519080825280601f01601f1916602001820160405280156112c0576020820181803683370190505b509050600182016020820185865187015b8082101561132c576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506112d1565b5050600386510660018114611348576002811461135b57611363565b603d6001830353603d6002830353611363565b603d60018303535b509195945050505050565b61137883836115d0565b61138560008484846113f7565b6106265760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e746572000000000000000000000000000060648201526084016104a1565b600073ffffffffffffffffffffffffffffffffffffffff84163b156115c5576040517f150b7a0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063150b7a029061146e9033908990889088906004016127e6565b6020604051808303816000875af19250505080156114c7575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526114c49181019061282f565b60015b61157a573d8080156114f5576040519150601f19603f3d011682016040523d82523d6000602084013e6114fa565b606091505b5080516000036115725760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e746572000000000000000000000000000060648201526084016104a1565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a0200000000000000000000000000000000000000000000000000000000149050610d0f565b506001949350505050565b73ffffffffffffffffffffffffffffffffffffffff82166116335760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016104a1565b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff16156116a55760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016104a1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604081208054600192906116db908490612716565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461178c57600080fd5b50565b6000602082840312156117a157600080fd5b81356117ac8161175e565b9392505050565b60005b838110156117ce5781810151838201526020016117b6565b838111156109995750506000910152565b600081518084526117f78160208601602086016117b3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006117ac60208301846117df565b60006020828403121561184e57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461187957600080fd5b919050565b6000806040838503121561189157600080fd5b61189a83611855565b946020939093013593505050565b6000806000606084860312156118bd57600080fd5b6118c684611855565b92506118d460208501611855565b9150604084013590509250925092565b6000602082840312156118f657600080fd5b6117ac82611855565b6000806040838503121561191257600080fd5b61191b83611855565b91506020830135801515811461193057600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000806080858703121561198057600080fd5b61198985611855565b935061199760208601611855565b925060408501359150606085013567ffffffffffffffff808211156119bb57600080fd5b818701915087601f8301126119cf57600080fd5b8135818111156119e1576119e161193b565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611a2757611a2761193b565b816040528281528a6020848701011115611a4057600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b60008060408385031215611a7757600080fd5b611a8083611855565b9150611a8e60208401611855565b90509250929050565b600181811c90821680611aab57607f821691505b602082108103611ae4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611b2857611b28611aea565b500690565b7f3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323081527f30302f737667222077696474683d223130323422206865696768743d2231303260208201527f34222066696c6c3d226e6f6e65223e3c706174682066696c6c3d2268736c2800604082015260008351611bb181605f8501602088016117b3565b7f2c20313030252c20313025292220643d224d3020306831303234763130323448605f918401918201527f307a22202f3e3c672066696c6c3d2268736c2800000000000000000000000000607f8201528351611c148160928401602088016117b3565b7f2c20313030252c2039302529223e3c7061746820643d224d393033203433372e609292909101918201527f35633020392e3131332d372e3338382031362e352d31362e352031362e35732d60b28201527f31362e352d372e3338372d31362e352d31362e3520372e3338382d31362e352060d28201527f31362e352d31362e352031362e3520372e3338372031362e352031362e357a4d60f28201527f3639382e3532392035363663362e39323120302031322e35332d352e353936206101128201527f31322e35332d31322e35762d353063302d362e39303420352e3630392d31322e6101328201527f352031322e3532392d31322e356832352e30353963362e393220302031322e356101528201527f323920352e3539362031322e3532392031322e35763530633020362e393034206101728201527f352e3630392031322e352031322e35332031322e357331322e3532392d352e356101928201527f39362031322e3532392d31322e35762d353063302d362e39303420352e3630396101b28201527f2d31322e352031322e35332d31322e356832352e30353963362e3932203020316101d28201527f322e35323920352e3539362031322e3532392031322e35763530633020362e396101f28201527f303420352e3630392031322e352031322e3532392031322e356833372e3538396102128201527f63362e393220302031322e3532392d352e3539362031322e3532392d31322e356102328201527f762d373563302d362e3930342d352e3630392d31322e352d31322e3532392d316102528201527f322e35732d31322e353320352e3539362d31322e35332031322e357635362e326102728201527f3561362e32363420362e3236342030203120312d31322e3532392030563437386102928201527f2e3563302d362e3930342d352e3630392d31322e352d31322e35332d31322e356102b28201527f483639382e353239632d362e393220302d31322e35323920352e3539362d31326102d28201527f2e3532392031322e35763735633020362e39303420352e3630392031322e35206102f28201527f31322e3532392031322e357a22202f3e3c7061746820643d224d3135372e36356103128201527f3520353431632d362e39333220302d31322e3535322d352e3539362d31322e356103328201527f35322d31322e35762d353063302d362e3930342d352e3631392d31322e352d316103528201527f322e3535312d31322e3553313230203437312e35393620313230203437382e356103728201527f763735633020362e39303420352e36322031322e352031322e3535322031322e6103928201527f35683135302e363263362e39333320302031322e3535322d352e3539362031326103b28201527f2e3535322d31322e35762d353063302d362e39303420352e3631392d31322e356103d28201527f2031322e3535322d31322e35683134342e33343563332e343635203020362e326103f28201527f373620322e37393820362e32373620362e3235732d322e38313120362e32352d6104128201527f362e32373620362e3235483332302e383238632d362e39333320302d31322e356104328201527f353220352e3539362d31322e3535322031322e357633372e35633020362e39306104528201527f3420352e3631392031322e352031322e3535322031322e35683135302e3632636104728201527f362e39333320302031322e3535322d352e3539362031322e3535322d31322e356104928201527f762d373563302d362e3930342d352e3631392d31322e352d31322e3535322d316104b28201527f322e35483238332e313732632d362e39333220302d31322e35353120352e35396104d28201527f362d31322e3535312031322e35763530633020362e3930342d352e36313920316104f28201527f322e352d31322e3535322031322e35682d32352e313033632d362e39333320306105128201527f2d31322e3535322d352e3539362d31322e3535322d31322e35762d353063302d6105328201527f362e3930342d352e36322d31322e352d31322e3535322d31322e35732d31322e6105528201527f35353220352e3539362d31322e3535322031322e35763530633020362e3930346105728201527f2d352e3631392031322e352d31322e3535312031322e35682d32352e3130347a6105928201527f6d3330312e3234322d362e3235633020332e3435322d322e38313120362e32356105b28201527f2d362e32373620362e3235483333392e363535632d332e34363520302d362e326105d28201527f37362d322e3739382d362e3237362d362e323573322e3831312d362e323520366105f28201527f2e3237362d362e3235683131322e39363663332e343635203020362e323736206106128201527f322e37393820362e32373620362e32357a4d343937203535332e3831386330206106328201527f362e39323920352e3632382031322e3534362031322e3537312031322e3534366106528201527f6831333261362e323820362e323820302030203120362e32383620362e3237326106728201527f20362e323820362e32382030203020312d362e32383620362e323733682d31336106928201527f32632d362e39343320302d31322e35373120352e3631362d31322e35373120316106b28201527f322e3534364131322e35362031322e3536203020302030203530392e353731206106d28201527f363034683135302e38353863362e39343320302031322e3537312d352e3631366106f28201527f2031322e3537312d31322e353435762d3131322e393163302d362e3932382d356107128201527f2e3632382d31322e3534352d31322e3537312d31322e353435483530392e35376107328201527f31632d362e39343320302d31322e35373120352e3631372d31322e35373120316107528201527f322e3534357637352e3237337a6d33372e3731342d36322e373237632d362e396107728201527f343320302d31322e35373120352e3631372d31322e3537312031322e353435766107928201527f32352e303931633020362e39323920352e3632382031322e3534362031322e356107b28201527f37312031322e353436683130302e35373263362e39343320302031322e3537316107d28201527f2d352e3631372031322e3537312d31322e353436762d32352e30393163302d366107f28201527f2e3932382d352e3632382d31322e3534352d31322e3537312d31322e353435486108128201527f3533342e3731347a222066696c6c2d72756c653d226576656e6f646422202f3e6108328201527f3c2f673e3c2f7376673e0000000000000000000000000000000000000000000061085282015261085c01949350505050565b7f7b226e616d65223a20227761676d6920230000000000000000000000000000008152600083516125f28160118501602088016117b3565b7f222c2022696d616765223a2022646174613a696d6167652f7376672b786d6c3b6011918401918201527f6261736536342c00000000000000000000000000000000000000000000000000603182015283516126558160388401602088016117b3565b7f227d00000000000000000000000000000000000000000000000000000000000060389290910191820152603a01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516126c381601d8501602087016117b3565b91909101601d0192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612711576127116126d0565b500390565b60008219821115612729576127296126d0565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361275f5761275f6126d0565b5060010190565b60008261277557612775611aea565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156127e1576127e16126d0565b500290565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152508360408301526080606083015261282560808301846117df565b9695505050505050565b60006020828403121561284157600080fd5b81516117ac8161175e56fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212201665a4f9111990d7529375848d3fd02c0121091a940da59e763eba826e7b077064736f6c634300080d0033', } as const export const daiContractConfig = {