diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 237a77d0e..dfc172fe2 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -300,6 +300,16 @@ func (v *VM) execute(ctx *Context, op Instruction) { } v.estack.InsertAt(a, 2) + case XDROP: + n := int(v.estack.Pop().BigInt().Int64()) + if n < 0 { + panic("invalid length") + } + e := v.estack.RemoveAt(n) + if e == nil { + panic("bad index") + } + case XSWAP: n := int(v.estack.Pop().BigInt().Int64()) if n < 0 { diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index 781df0f8f..8d13973ba 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -408,6 +408,44 @@ func TestOVERgood(t *testing.T) { assert.Equal(t, 3, vm.estack.Len()) } +func TestXDROPbadNoitem(t *testing.T) { + prog := makeProgram(XDROP) + vm := load(prog) + vm.Run() + assert.Equal(t, true, vm.state.HasFlag(faultState)) +} + +func TestXDROPbadNoN(t *testing.T) { + prog := makeProgram(XDROP) + vm := load(prog) + vm.estack.PushVal(1) + vm.estack.PushVal(2) + vm.Run() + assert.Equal(t, true, vm.state.HasFlag(faultState)) +} + +func TestXDROPbadNegative(t *testing.T) { + prog := makeProgram(XDROP) + vm := load(prog) + vm.estack.PushVal(1) + vm.estack.PushVal(-1) + vm.Run() + assert.Equal(t, true, vm.state.HasFlag(faultState)) +} + +func TestXDROPgood(t *testing.T) { + prog := makeProgram(XDROP) + vm := load(prog) + vm.estack.PushVal(0) + vm.estack.PushVal(1) + vm.estack.PushVal(2) + vm.estack.PushVal(2) + vm.Run() + assert.Equal(t, false, vm.state.HasFlag(faultState)) + assert.Equal(t, 2, vm.estack.Len()) + assert.Equal(t, int64(2), vm.estack.Peek(0).BigInt().Int64()) + assert.Equal(t, int64(1), vm.estack.Peek(1).BigInt().Int64()) +} func makeProgram(opcodes ...Instruction) []byte { prog := make([]byte, len(opcodes)+1) // RET