|
4 | 4 | "bytes" |
5 | 5 | "encoding/binary" |
6 | 6 | "fmt" |
| 7 | + "math" |
7 | 8 | "math/big" |
8 | 9 | "testing" |
9 | 10 |
|
@@ -1244,6 +1245,89 @@ func TestEVMBatchRun(t *testing.T) { |
1244 | 1245 | require.Equal(t, num, new(big.Int).SetBytes(res.ReturnedData).Int64()) |
1245 | 1246 | }) |
1246 | 1247 | }) |
| 1248 | + |
| 1249 | + // run a batch of two transactions. The sum of their gas usage would overflow an uint46 |
| 1250 | + // so the batch run should fail with an overflow error. |
| 1251 | + t.Run("Batch run evm gas overflow", func(t *testing.T) { |
| 1252 | + t.Parallel() |
| 1253 | + RunWithNewEnvironment(t, |
| 1254 | + chain, func( |
| 1255 | + ctx fvm.Context, |
| 1256 | + vm fvm.VM, |
| 1257 | + snapshot snapshot.SnapshotTree, |
| 1258 | + testContract *TestContract, |
| 1259 | + testAccount *EOATestAccount, |
| 1260 | + ) { |
| 1261 | + sc := systemcontracts.SystemContractsForChain(chain.ChainID()) |
| 1262 | + batchRunCode := []byte(fmt.Sprintf( |
| 1263 | + ` |
| 1264 | + import EVM from %s |
| 1265 | +
|
| 1266 | + transaction(txs: [[UInt8]], coinbaseBytes: [UInt8; 20]) { |
| 1267 | + execute { |
| 1268 | + let coinbase = EVM.EVMAddress(bytes: coinbaseBytes) |
| 1269 | + let batchResults = EVM.batchRun(txs: txs, coinbase: coinbase) |
| 1270 | + } |
| 1271 | + } |
| 1272 | + `, |
| 1273 | + sc.EVMContract.Address.HexWithPrefix(), |
| 1274 | + )) |
| 1275 | + |
| 1276 | + coinbaseAddr := types.Address{1, 2, 3} |
| 1277 | + coinbaseBalance := getEVMAccountBalance(t, ctx, vm, snapshot, coinbaseAddr) |
| 1278 | + require.Zero(t, types.BalanceToBigInt(coinbaseBalance).Uint64()) |
| 1279 | + |
| 1280 | + batchCount := 2 |
| 1281 | + txBytes := make([]cadence.Value, batchCount) |
| 1282 | + |
| 1283 | + tx := testAccount.PrepareSignAndEncodeTx(t, |
| 1284 | + testContract.DeployedAt.ToCommon(), |
| 1285 | + testContract.MakeCallData(t, "storeWithLog", big.NewInt(0)), |
| 1286 | + big.NewInt(0), |
| 1287 | + uint64(200_000), |
| 1288 | + big.NewInt(1), |
| 1289 | + ) |
| 1290 | + |
| 1291 | + txBytes[0] = cadence.NewArray( |
| 1292 | + unittest.BytesToCdcUInt8(tx), |
| 1293 | + ).WithType(stdlib.EVMTransactionBytesCadenceType) |
| 1294 | + |
| 1295 | + tx = testAccount.PrepareSignAndEncodeTx(t, |
| 1296 | + testContract.DeployedAt.ToCommon(), |
| 1297 | + testContract.MakeCallData(t, "storeWithLog", big.NewInt(1)), |
| 1298 | + big.NewInt(0), |
| 1299 | + math.MaxUint64-uint64(100_000), |
| 1300 | + big.NewInt(1), |
| 1301 | + ) |
| 1302 | + |
| 1303 | + txBytes[1] = cadence.NewArray( |
| 1304 | + unittest.BytesToCdcUInt8(tx), |
| 1305 | + ).WithType(stdlib.EVMTransactionBytesCadenceType) |
| 1306 | + |
| 1307 | + coinbase := cadence.NewArray( |
| 1308 | + unittest.BytesToCdcUInt8(coinbaseAddr.Bytes()), |
| 1309 | + ).WithType(stdlib.EVMAddressBytesCadenceType) |
| 1310 | + |
| 1311 | + txs := cadence.NewArray(txBytes). |
| 1312 | + WithType(cadence.NewVariableSizedArrayType( |
| 1313 | + stdlib.EVMTransactionBytesCadenceType, |
| 1314 | + )) |
| 1315 | + |
| 1316 | + txBody, err := flow.NewTransactionBodyBuilder(). |
| 1317 | + SetScript(batchRunCode). |
| 1318 | + SetPayer(sc.FlowServiceAccount.Address). |
| 1319 | + AddArgument(json.MustEncode(txs)). |
| 1320 | + AddArgument(json.MustEncode(coinbase)). |
| 1321 | + Build() |
| 1322 | + require.NoError(t, err) |
| 1323 | + |
| 1324 | + state, output, err := vm.Run(ctx, fvm.Transaction(txBody, 0), snapshot) |
| 1325 | + require.NoError(t, err) |
| 1326 | + require.Error(t, output.Err) |
| 1327 | + require.ErrorContains(t, output.Err, "insufficient computation") |
| 1328 | + require.Empty(t, state.WriteSet) |
| 1329 | + }) |
| 1330 | + }) |
1247 | 1331 | } |
1248 | 1332 |
|
1249 | 1333 | func TestEVMBlockData(t *testing.T) { |
|
0 commit comments