mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
returnWithData, revertWithData
arbitrary-length return or revert (currently, can't test it, since we check "error", and actual revert data is hidden. will be probably needed when testing paymaster.)
This commit is contained in:
parent
6e2e44f32b
commit
6b7385d6a7
2 changed files with 38 additions and 15 deletions
|
|
@ -83,20 +83,38 @@ func (tt *testContextBuilder) withCode(addr string, code []byte, balance int64)
|
||||||
return tt
|
return tt
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate the code to return the given byte array (up to 32 bytes)
|
// create code to copy data into memory at the given offset
|
||||||
func returnData(data []byte) []byte {
|
// NOTE: if data is not in 32-byte multiples, it will override the next bytes
|
||||||
datalen := len(data)
|
// used by RETURN/REVERT
|
||||||
if datalen > 32 {
|
func copyToMemory(data []byte, offset uint) []byte {
|
||||||
panic(fmt.Errorf("data length is too big %v", data))
|
ret := []byte{}
|
||||||
|
for len(data) > 32 {
|
||||||
|
ret = append(ret, createCode(vm.PUSH32, data[0:32], vm.PUSH2, uint16(offset), vm.MSTORE)...)
|
||||||
|
data = data[32:]
|
||||||
|
offset = offset + 32
|
||||||
}
|
}
|
||||||
|
|
||||||
PUSHn := byte(int(vm.PUSH0) + datalen)
|
if len(data) > 0 {
|
||||||
ret := createCode(PUSHn, data, vm.PUSH0, vm.MSTORE, vm.PUSH1, datalen, vm.PUSH1, 0, vm.RETURN)
|
PUSHn := byte(int(vm.PUSH0) + len(data))
|
||||||
|
ret = append(ret, createCode(PUSHn, data, vm.PUSH2, uint16(offset), vm.MSTORE)...)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// revert with given data
|
||||||
|
func revertWithData(data []byte) []byte {
|
||||||
|
ret := append(copyToMemory(data, 0), createCode(vm.PUSH2, uint16(len(data)), vm.PUSH0, vm.REVERT)...)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate the code to return the given byte array (up to 32 bytes)
|
||||||
|
func returnWithData(data []byte) []byte {
|
||||||
|
ret := append(copyToMemory(data, 0), createCode(vm.PUSH2, uint16(len(data)), vm.PUSH0, vm.RETURN)...)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func createAccountCode() []byte {
|
func createAccountCode() []byte {
|
||||||
return returnData(core.PackValidationData(core.MAGIC_VALUE_SENDER, 0, 0))
|
return returnWithData(core.PackValidationData(core.MAGIC_VALUE_SENDER, 0, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
// create EVM code from OpCode, byte and []bytes
|
// create EVM code from OpCode, byte and []bytes
|
||||||
|
|
@ -115,9 +133,11 @@ func createCode(items ...interface{}) []byte {
|
||||||
buffer.Write(v)
|
buffer.Write(v)
|
||||||
case int8:
|
case int8:
|
||||||
buffer.WriteByte(byte(v))
|
buffer.WriteByte(byte(v))
|
||||||
|
case uint16:
|
||||||
|
buffer.Write([]byte{byte(v >> 8), byte(v)})
|
||||||
case int:
|
case int:
|
||||||
if v >= 256 {
|
if v >= 256 {
|
||||||
panic(fmt.Errorf("int defaults to int8 (byte). int16, etc: %v", v))
|
panic(fmt.Errorf("int defaults to int8 (byte). use int16, etc: %v", v))
|
||||||
}
|
}
|
||||||
buffer.WriteByte(byte(v))
|
buffer.WriteByte(byte(v))
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/tests"
|
"github.com/ethereum/go-ethereum/tests"
|
||||||
|
"github.com/status-im/keycard-go/hexutils"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -43,7 +44,7 @@ func TestValidationFailure_no_balance(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidationFailure_sigerror(t *testing.T) {
|
func TestValidationFailure_sigerror(t *testing.T) {
|
||||||
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER, returnData(core.PackValidationData(core.MAGIC_VALUE_SIGFAIL, 0, 0)), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER, returnWithData(core.PackValidationData(core.MAGIC_VALUE_SIGFAIL, 0, 0)), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
ValidationGas: uint64(1000000000),
|
ValidationGas: uint64(1000000000),
|
||||||
GasFeeCap: big.NewInt(1000000000),
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
}, "account signature error")
|
}, "account signature error")
|
||||||
|
|
@ -104,9 +105,11 @@ func TestValidationFailure_account_revert(t *testing.T) {
|
||||||
}, "execution reverted")
|
}, "execution reverted")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidationFailure_account_out_of_range(t *testing.T) {
|
func TestValidationFailure_account_revert_with_reason(t *testing.T) {
|
||||||
|
// cast abi-encode 'Error(string)' hello
|
||||||
|
reason := hexutils.HexToBytes("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000")
|
||||||
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER,
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER,
|
||||||
createCode(vm.PUSH0, vm.DUP1, vm.REVERT), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
revertWithData(reason), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
ValidationGas: uint64(1000000000),
|
ValidationGas: uint64(1000000000),
|
||||||
GasFeeCap: big.NewInt(1000000000),
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
}, "execution reverted")
|
}, "execution reverted")
|
||||||
|
|
@ -114,7 +117,7 @@ func TestValidationFailure_account_out_of_range(t *testing.T) {
|
||||||
|
|
||||||
func TestValidationFailure_account_wrong_return_length(t *testing.T) {
|
func TestValidationFailure_account_wrong_return_length(t *testing.T) {
|
||||||
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER,
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER,
|
||||||
returnData([]byte{1, 2, 3}), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
returnWithData([]byte{1, 2, 3}), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
ValidationGas: uint64(1000000000),
|
ValidationGas: uint64(1000000000),
|
||||||
GasFeeCap: big.NewInt(1000000000),
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
}, "invalid account return data length")
|
}, "invalid account return data length")
|
||||||
|
|
@ -122,7 +125,7 @@ func TestValidationFailure_account_wrong_return_length(t *testing.T) {
|
||||||
|
|
||||||
func TestValidationFailure_account_no_return_value(t *testing.T) {
|
func TestValidationFailure_account_no_return_value(t *testing.T) {
|
||||||
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER,
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER,
|
||||||
returnData([]byte{}), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
returnWithData([]byte{}), DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
ValidationGas: uint64(1000000000),
|
ValidationGas: uint64(1000000000),
|
||||||
GasFeeCap: big.NewInt(1000000000),
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
}, "invalid account return data length")
|
}, "invalid account return data length")
|
||||||
|
|
@ -131,7 +134,7 @@ func TestValidationFailure_account_no_return_value(t *testing.T) {
|
||||||
func TestValidationFailure_account_wrong_return_value(t *testing.T) {
|
func TestValidationFailure_account_wrong_return_value(t *testing.T) {
|
||||||
// create buffer of 32 byte array
|
// create buffer of 32 byte array
|
||||||
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER,
|
handleTransaction(newTestContextBuilder(t).withCode(DEFAULT_SENDER,
|
||||||
returnData(make([]byte, 32)),
|
returnWithData(make([]byte, 32)),
|
||||||
DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
DEFAULT_BALANCE), types.Rip7560AccountAbstractionTx{
|
||||||
ValidationGas: uint64(1000000000),
|
ValidationGas: uint64(1000000000),
|
||||||
GasFeeCap: big.NewInt(1000000000),
|
GasFeeCap: big.NewInt(1000000000),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue