HIGH severity: [FTN-1] Wrong activity calculations. **Severity:** High

**Path:** core/vm/evm.go

**Description:** In functions `CallCode` and `DelegateCall`, activity parameters are incorrectly calculated.

The problem is that when the `DelegateCall` and `CallCode` are called, the execution context changes. This can cause problems when counting...

Vulnerable code:
func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
    // Fail if we're trying to execute above the call depth limit
    if evm.depth > int(params.CallCreateDepth) {
        return nil, gas, ErrDepth
    }

    initialGas := gas
    // Fail if we're trying to transfer more than the available balance
    // Note although it's noop to transfer X ether to caller itself. But
    // if caller doesn't have enough balance, it would be an error to allow
    // over-charging itself. So the check here is necessary.
    if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
        return nil, gas, ErrInsufficientBalance
    }
    snapshot := evm.StateDB.Snapshot()

    // Invoke tracer hooks that signal entering/exiting a call frame
    if evm.Config.Debug {
        evm.Config.Tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value)
        defer func(startGas uint64) {
            evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
        }(gas)
    }

    // It is allowed to call precompiles, even via delegatecall
    if p, isPrecompile := evm.precompile(addr); isPrecompile {
        ret, gas, err = RunPrecompiledContract(p, input, gas)
    } else {
        addrCopy := addr
        // Initialise a new contract and set the code that is to be used by the EVM.
        // The contract is a scoped environment for this execution context only.
        contract := NewContract(caller, AccountRef(caller.Address()), value, gas)
        contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
        ret, err = evm.interpreter.Run(contract, input, false)
        gas = contract.Gas

        memGas, err := evm.memoryGas(input)
        if err != nil {
            return nil, gas, err
        }
        if caller.Address() != evm.Origin {
            memGas = 0
        }
        evm.StateDB.AddActivity(addrCopy, initialGas-contract.Gas-contract.OthersGas+memGas)
        evm.StateDB.AddActivities(&types.Activity{
            Address:       addrCopy,
            Activity:      evm.StateDB.GetActivity(addrCopy),
            DeltaActivity: initialGas - contract.Gas - contract.OthersGas,
        })
    }
    if err != nil {
        evm.StateDB.RevertToSnapshot(snapshot)
        if err != ErrExecutionReverted {
            gas = 0
        }
    }
    return ret, gas, err
}

func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
    // Fail if we're trying to execute above the call depth limit
    if evm.depth > int(params.CallCreateDepth) {
        return nil, gas, ErrDepth
    }

    initialGas := gas

    snapshot := evm.StateDB.Snapshot()

    // Invoke tracer hooks that signal entering/exiting a call frame
    if evm.Config.Debug {
        evm.Config.Tracer.CaptureEnter(DELEGATECALL, caller.Address(), addr, input, gas, nil)
        defer func(startGas uint64) {
            evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
        }(gas)
    }

    // It is allowed to call precompiles, even via delegatecall
    if p, isPrecompile := evm.precompile(addr); isPrecompile {
        ret, gas, err = RunPrecompiledContract(p, input, gas)
    } else {
        addrCopy := addr
        // Initialise a new contract and make initialise the delegate values
        contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate()
        contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy))
        ret, err = evm.interpreter.Run(contract, input, false)
        gas = contract.Gas

        evm.StateDB.AddActivity(addrCopy, initialGas-contract.Gas-contract.OthersGas)
        evm.StateDB.AddActivities(&types.Activity{
            Address:       addrCopy,
            Activity:      evm.StateDB.GetActivity(addrCopy),
            DeltaActivity: initialGas - contract.Gas - contract.OthersGas,
        })
    }
    if err != nil {
        evm.StateDB.RevertToSnapshot(snapshot)
        if err != ErrExecutionReverted {
            gas = 0
        }
    }
    return ret, gas, err
}