@tokamak-zk-evm/synthesizer
Version:
Tokamak zk-EVM Synthesizer - Processes Ethereum transactions into wire maps for Tokamak zk-SNARK proof generation
106 lines • 6.66 kB
JavaScript
import { keccak256 } from 'ethereum-cryptography/keccak';
import { hexToBytes, Address, Account } from '@synthesizer-libs/util';
const IMPLEMENTATION_SLOT = '0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3';
export const setupUSDCFromCalldata = async (evm, proxyAddr, implementationV1Addr, implementationV2Addr, proxyCode, v1Code, v2Code, proxyStorageLayout, v1StorageLayout, v2StorageLayout, calldata, sender) => {
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) => {
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) => {
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('==================');
};
//# sourceMappingURL=usdcEvmSetup.js.map