@Override
  public OperationResult execute(final MessageFrame frame, final EVM evm) {
    if (frame.isStatic()) {
      return new OperationResult(0, ExceptionalHaltReason.ILLEGAL_STATE_CHANGE);
    }

    final Bytes toAddressBytes = frame.getStackItem(0);
    final int numberOfLowBytes = toAddressBytes.size() - toAddressBytes.numberOfLeadingZeroBytes();
    if (numberOfLowBytes > 20) {
      return new OperationResult(0, ExceptionalHaltReason.ADDRESS_OUT_OF_RANGE);
    }

    final Address to = Words.toAddress(toAddressBytes);
    final Wei value = Wei.wrap(frame.getStackItem(1));
    final boolean hasValue = value.greaterThan(Wei.ZERO);
    final Account recipient = frame.getWorldUpdater().get(to);

    final boolean accountIsWarm = frame.warmUpAddress(to);

    final long cost = cost(to, hasValue, recipient, accountIsWarm);
    if (frame.getRemainingGas() < cost) {
      return new OperationResult(cost, ExceptionalHaltReason.INSUFFICIENT_GAS);
    }

    if (!hasValue || Objects.equals(frame.getSenderAddress(), to)) {
      frame.popStackItems(getStackItemsConsumed());
      frame.pushStackItem(LEGACY_SUCCESS_STACK_ITEM);
      return new OperationResult(cost, null);
    }

    final MutableAccount senderAccount = frame.getWorldUpdater().getSenderAccount(frame);
    if (value.compareTo(senderAccount.getBalance()) > 0) {
      frame.popStackItems(getStackItemsConsumed());
      frame.pushStackItem(LEGACY_FAILURE_STACK_ITEM);
      return new OperationResult(cost, null);
    }

    final MutableAccount recipientAccount = frame.getWorldUpdater().getOrCreate(to);
    senderAccount.decrementBalance(value);
    recipientAccount.incrementBalance(value);

    frame.popStackItems(getStackItemsConsumed());
    frame.pushStackItem(LEGACY_SUCCESS_STACK_ITEM);
    return new OperationResult(cost, null);
  }
Instantiates a new Abstract operation.

@param gasCalculator the gas calculator
evm/src/main/java/org/hyperledger/besu/evm/operation/PayOperation.java