import type { AvmContext } from '../avm_context.js'; import { Field, Uint1, Uint32, Uint64, Uint128 } from '../avm_memory_types.js'; import { InstructionExecutionError } from '../errors.js'; import { Opcode, OperandType } from '../serialization/instruction_serialization.js'; import { Addressing } from './addressing_mode.js'; import { Instruction } from './instruction.js'; export enum EnvironmentVariable { ADDRESS, SENDER, TRANSACTIONFEE, CHAINID, VERSION, BLOCKNUMBER, TIMESTAMP, MINFEEPERL2GAS, MINFEEPERDAGAS, ISSTATICCALL, L2GASLEFT, DAGASLEFT, } function getValue(varEnum: EnvironmentVariable, ctx: AvmContext) { switch (varEnum) { case EnvironmentVariable.ADDRESS: return new Field(ctx.environment.address.toField()); case EnvironmentVariable.SENDER: return new Field(ctx.environment.sender.toField()); case EnvironmentVariable.TRANSACTIONFEE: return new Field(ctx.environment.transactionFee); case EnvironmentVariable.CHAINID: return new Field(ctx.environment.globals.chainId); case EnvironmentVariable.VERSION: return new Field(ctx.environment.globals.version); case EnvironmentVariable.BLOCKNUMBER: return new Uint32(ctx.environment.globals.blockNumber); case EnvironmentVariable.TIMESTAMP: return new Uint64(ctx.environment.globals.timestamp); case EnvironmentVariable.MINFEEPERL2GAS: return new Uint128(ctx.environment.globals.gasFees.feePerL2Gas); case EnvironmentVariable.MINFEEPERDAGAS: return new Uint128(ctx.environment.globals.gasFees.feePerDaGas); case EnvironmentVariable.ISSTATICCALL: return new Uint1(ctx.environment.isStaticCall ? 1 : 0); case EnvironmentVariable.L2GASLEFT: return new Uint32(ctx.machineState.l2GasLeft); case EnvironmentVariable.DAGASLEFT: return new Uint32(ctx.machineState.daGasLeft); default: throw new InstructionExecutionError(`Invalid GETENVVAR var enum ${varEnum}`); } } export class GetEnvVar extends Instruction { public static readonly type: string = 'GETENVVAR'; public static readonly opcode: Opcode = Opcode.GETENVVAR_16; static readonly wireFormat16: OperandType[] = [ OperandType.UINT8, // opcode OperandType.UINT8, // addressing_mode OperandType.UINT16, // dstOffset OperandType.UINT8, // variable enum (immediate) ]; constructor( private addressingMode: number, private dstOffset: number, private varEnum: number, ) { super(); } public async execute(context: AvmContext): Promise { const memory = context.machineState.memory; const addressing = Addressing.fromWire(this.addressingMode); context.machineState.consumeGas( this.baseGasCost(addressing.indirectOperandsCount(), addressing.relativeOperandsCount()), ); const operands = [this.dstOffset]; const [dstOffset] = addressing.resolve(operands, memory); const value = getValue(this.varEnum as EnvironmentVariable, context); memory.set(dstOffset, value); } }