package runtime import ( "errors" "github.com/nspcc-dev/neo-go/pkg/core/interop" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) // GasLeft returns remaining amount of GAS. func GasLeft(ic *interop.Context) error { if ic.VM.GasLimit == -1 { ic.VM.Estack().PushVal(ic.VM.GasLimit) } else { ic.VM.Estack().PushVal(ic.VM.GasLimit - ic.VM.GasConsumed()) } return nil } // GetNotifications returns notifications emitted by current contract execution. func GetNotifications(ic *interop.Context) error { item := ic.VM.Estack().Pop().Item() notifications := ic.Notifications if _, ok := item.(stackitem.Null); !ok { b, err := item.TryBytes() if err != nil { return err } u, err := util.Uint160DecodeBytesBE(b) if err != nil { return err } notifications = []state.NotificationEvent{} for i := range ic.Notifications { if ic.Notifications[i].ScriptHash.Equals(u) { notifications = append(notifications, ic.Notifications[i]) } } } if len(notifications) > vm.MaxStackSize { return errors.New("too many notifications") } arr := stackitem.NewArray(make([]stackitem.Item, 0, len(notifications))) for i := range notifications { ev := stackitem.NewArray([]stackitem.Item{ stackitem.NewByteArray(notifications[i].ScriptHash.BytesBE()), stackitem.Make(notifications[i].Name), stackitem.DeepCopy(notifications[i].Item).(*stackitem.Array), }) arr.Append(ev) } ic.VM.Estack().PushVal(arr) return nil } // GetInvocationCounter returns how many times current contract was invoked during current tx execution. func GetInvocationCounter(ic *interop.Context) error { currentScriptHash := ic.VM.GetCurrentScriptHash() count, ok := ic.VM.Invocations[currentScriptHash] if !ok { count = 1 ic.VM.Invocations[currentScriptHash] = count } ic.VM.Estack().PushVal(count) return nil }