UNPKG

@tokamak-zk-evm/synthesizer

Version:

Tokamak zk-EVM Synthesizer - Processes Ethereum transactions into wire maps for Tokamak zk-SNARK proof generation

208 lines (174 loc) 7.62 kB
import { keccak256 } from 'ethereum-cryptography/keccak' import { hexToBytes, Address, Account } from '@synthesizer-libs/util'; import { EVM } from '../../evm.js'; interface StorageItem { astId: number; contract: string; label: string; offset: number; slot: string; type: string; } interface StorageLayout { storageLayout: { storage: StorageItem[]; types: { [key: string]: { encoding: string; label: string; numberOfBytes: string; key?: string; value?: string; }; }; }; } const IMPLEMENTATION_SLOT = '0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3' export const setupUSDCFromCalldata = async ( evm: EVM, proxyAddr: Address, implementationV1Addr: Address, implementationV2Addr: Address, proxyCode: Uint8Array, v1Code: Uint8Array, v2Code: Uint8Array, proxyStorageLayout: StorageLayout, v1StorageLayout: StorageLayout, v2StorageLayout: StorageLayout, calldata: string, sender: Address, ) => { console.log('=== Setting up USDC Environment ==='); console.log('Proxy address:', proxyAddr.toString()); console.log('Implementation V1 address:', implementationV1Addr.toString()); console.log('Implementation V2 address:', implementationV2Addr.toString()); // Setup all contract accounts await evm.stateManager.putAccount(proxyAddr, new Account()) await evm.stateManager.putAccount(implementationV1Addr, new Account()) await evm.stateManager.putAccount(implementationV2Addr, new Account()) await evm.stateManager.putAccount(sender, new Account()) // Deploy all contract codes await evm.stateManager.putCode(proxyAddr, proxyCode) await evm.stateManager.putCode(implementationV1Addr, v1Code) await evm.stateManager.putCode(implementationV2Addr, v2Code) // Verify code deployment const proxyDeployedCode = await evm.stateManager.getCode(proxyAddr) const v1DeployedCode = await evm.stateManager.getCode(implementationV1Addr) const v2DeployedCode = await evm.stateManager.getCode(implementationV2Addr) // Setup delegation chain with verification await evm.stateManager.putStorage( proxyAddr, hexToBytes(IMPLEMENTATION_SLOT), hexToBytes('0x' + implementationV1Addr.toString().slice(2).padStart(64, '0')) ) await evm.stateManager.putStorage( implementationV1Addr, hexToBytes(IMPLEMENTATION_SLOT), hexToBytes('0x' + implementationV2Addr.toString().slice(2).padStart(64, '0')) ) // Verify delegation chain const proxyImpl = await evm.stateManager.getStorage(proxyAddr, hexToBytes(IMPLEMENTATION_SLOT)) const v1Impl = await evm.stateManager.getStorage(implementationV1Addr, hexToBytes(IMPLEMENTATION_SLOT)) console.log('Proxy implementation:', Buffer.from(proxyImpl).toString('hex')); console.log('V1 implementation:', Buffer.from(v1Impl).toString('hex')); // Helper function to find balance slot in storage layout const findBalanceSlot = (layout: StorageLayout) => { return layout.storageLayout.storage.find( item => item.label === '_balances' || item.label === 'balances' )?.slot } // Get balance slots from each layout const proxyBalanceSlot = findBalanceSlot(proxyStorageLayout) const v1BalanceSlot = findBalanceSlot(v1StorageLayout) const v2BalanceSlot = findBalanceSlot(v2StorageLayout) // Parse calldata const params = calldata.slice(10) const functionSig = calldata.slice(0, 10) switch(functionSig) { case '0xa9059cbb': { // transfer const to = '0x' + params.slice(24, 64) const amount = BigInt('0x' + params.slice(64)) console.log('=== Setup Debug Info ===') console.log('Sender:', sender.toString()) console.log('To:', to) console.log('Amount:', amount.toString()) // Setup recipient account await evm.stateManager.putAccount(new Address(hexToBytes(to)), new Account()) // Setup balances in all contracts if needed if (v2BalanceSlot) { // Use V2's layout as it's the final implementation console.log('v2BalanceSlot:', v2BalanceSlot) const balanceKey = keccak256( hexToBytes( '0x' + sender.toString().slice(2).padStart(64, '0') + v2BalanceSlot.padStart(64, '0') ) ) // Set initial balance for sender const initialBalance = amount + BigInt(1000) // Some buffer await evm.stateManager.putStorage( proxyAddr, // Store in proxy's storage balanceKey, hexToBytes('0x' + initialBalance.toString(16).padStart(64, '0')) ) const senderBalanceSlot = keccak256( hexToBytes( '0x' + sender.toString().slice(2).padStart(64, '0') + v2BalanceSlot.padStart(64, '0'), ), ); // 검증을 위해 저장된 값 확인 const storedBalance = await evm.stateManager.getStorage(proxyAddr, senderBalanceSlot); console.log('Stored balance:', Buffer.from(storedBalance).toString('hex')); } break } case '0x095ea7b3': { // approve const spender = '0x' + params.slice(24, 64) const amount = BigInt('0x' + params.slice(64)) // Setup spender account await evm.stateManager.putAccount(new Address(hexToBytes(spender)), new Account()) // Find allowance slots const findAllowanceSlot = (layout: StorageLayout) => { return layout.storageLayout.storage.find( item => item.label === 'allowed' )?.slot } const v2AllowanceSlot = findAllowanceSlot(v2StorageLayout) if (v2AllowanceSlot) { // Calculate storage slot for allowance // allowances[owner][spender] // console.log('v2AllowanceSlot:', v2AllowanceSlot) const ownerKey = keccak256( hexToBytes( '0x' + sender.toString().slice(2).padStart(64, '0') + v2AllowanceSlot.padStart(64, '0') ) ) const spenderKey = keccak256( hexToBytes( '0x' + spender.slice(2).padStart(64, '0') + ownerKey.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '').padStart(64, '0') ) ) // Set initial allowance in proxy's storage await evm.stateManager.putStorage( proxyAddr, // Store in proxy's storage spenderKey, hexToBytes('0x' + amount.toString(16).padStart(64, '0')) // ) console.log('Setup allowance mapping:', { owner: sender.toString(), spender: spender, slot: v2AllowanceSlot, storageKey: Buffer.from(spenderKey).toString('hex') }) // Verify the allowance was set const currentAllowance = await evm.stateManager.getStorage(proxyAddr, spenderKey) console.log('Current allowance:', BigInt('0x' + Buffer.from(currentAllowance).toString('hex')).toString()) } break } } console.log('USDC Environment setup completed') console.log('==================') }