Skip to content

Commit

Permalink
chore: apply suggestions after code review
Browse files Browse the repository at this point in the history
  • Loading branch information
novusnota committed Sep 15, 2024
1 parent af51e03 commit b372017
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 251 deletions.
221 changes: 60 additions & 161 deletions src/test/exit-codes/compute-phase-errors.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { toNano } from "@ton/core";
import { Blockchain, SandboxContract, TreasuryContract } from "@ton/sandbox";
import { ComputePhaseErrorsTester as TestContract } from "./contracts/output/compute-phase-errors_ComputePhaseErrorsTester";
import {
ComputePhaseErrorsTester as TestContract,
ExitCode4,
} from "./contracts/output/compute-phase-errors_ComputePhaseErrorsTester";
import "@ton/test-utils";

describe("compute phase errors", () => {
Expand Down Expand Up @@ -33,220 +36,116 @@ describe("compute phase errors", () => {

// 0: success
it("should test exit code 0", async () => {
const sendResult = await contract.send(
treasure.getSender(),
{ value: toNano("10") },
"0",
);

expect(sendResult.transactions).toHaveTransaction({
from: treasure.address,
to: contract.address,
success: true,
exitCode: 0,
});
await testComputePhaseExitCode(0, contract, treasure);
});

// 1: alt. success code
it("should test exit code 1", async () => {
const sendResult = await contract.send(
treasure.getSender(),
{ value: toNano("10") },
"1",
);

expect(sendResult.transactions).toHaveTransaction({
from: treasure.address,
to: contract.address,
success: true,
exitCode: 1,
});
await testComputePhaseExitCode(1, contract, treasure);
});

// 2: stack underflow
it("should test exit code 2", async () => {
const sendResult = await contract.send(
treasure.getSender(),
{ value: toNano("10") },
"2",
);

expect(sendResult.transactions).toHaveTransaction({
from: treasure.address,
to: contract.address,
success: false,
exitCode: 2,
});
await testComputePhaseExitCode(2, contract, treasure);
});

// 3: Stack overflow
it("should test exit code 3", async () => {
const sendResult = await contract.send(
treasure.getSender(),
{ value: toNano("10") },
"3",
);

expect(sendResult.transactions).toHaveTransaction({
from: treasure.address,
to: contract.address,
success: false,
exitCode: 3,
});
await testComputePhaseExitCode(3, contract, treasure);
});

// 4: Integer overflow
it("should test exit code 4", async () => {
const sendResult = await contract.send(
treasure.getSender(),
{ value: toNano("10") },
{
$$type: "ExitCode4",
val0: BigInt(0),
val1: BigInt(1),
},
);

expect(sendResult.transactions).toHaveTransaction({
from: treasure.address,
to: contract.address,
success: false,
exitCode: 4,
});
await testComputePhaseExitCode(4, contract, treasure);
});

// 5: Integer out of range
it("should test exit code 5", async () => {
const sendResult = await contract.send(
treasure.getSender(),
{ value: toNano("10") },
"5",
);

expect(sendResult.transactions).toHaveTransaction({
from: treasure.address,
to: contract.address,
success: false,
exitCode: 5,
});
await testComputePhaseExitCode(5, contract, treasure);
});

// 6: Invalid opcode
it("should test exit code 6", async () => {
const sendResult = await contract.send(
treasure.getSender(),
{ value: toNano("10") },
"6",
);

expect(sendResult.transactions).toHaveTransaction({
from: treasure.address,
to: contract.address,
success: false,
exitCode: 6,
});
await testComputePhaseExitCode(8, contract, treasure);
});

// 7: Type check error
it("should test exit code 7", async () => {
const sendResult = await contract.send(
treasure.getSender(),
{ value: toNano("10") },
"7",
);

expect(sendResult.transactions).toHaveTransaction({
from: treasure.address,
to: contract.address,
success: false,
exitCode: 7,
});
await testComputePhaseExitCode(7, contract, treasure);
});

// 8: Cell overflow
it("should test exit code 8", async () => {
const sendResult = await contract.send(
treasure.getSender(),
{ value: toNano("10") },
"8",
);

expect(sendResult.transactions).toHaveTransaction({
from: treasure.address,
to: contract.address,
success: false,
exitCode: 8,
});
await testComputePhaseExitCode(8, contract, treasure);
});

// 9: Cell underflow
it("should test exit code 9", async () => {
const sendResult = await contract.send(
treasure.getSender(),
{ value: toNano("10") },
"9",
);

expect(sendResult.transactions).toHaveTransaction({
from: treasure.address,
to: contract.address,
success: false,
exitCode: 9,
});
await testComputePhaseExitCode(9, contract, treasure);
});

// 10: Dictionary error
it("should test exit code 10", async () => {
const sendResult = await contract.send(
treasure.getSender(),
{ value: toNano("10") },
"10",
);

expect(sendResult.transactions).toHaveTransaction({
from: treasure.address,
to: contract.address,
success: false,
exitCode: 10,
});
await testComputePhaseExitCode(10, contract, treasure);
});

// 11: "Unknown" error
// NOTE: Thrown in various unrelated cases
it("should test exit code 11", async () => {
const sendResult = await contract.send(
treasure.getSender(),
{ value: toNano("10") },
"11",
);

expect(sendResult.transactions).toHaveTransaction({
from: treasure.address,
to: contract.address,
success: false,
exitCode: 11,
});
await testComputePhaseExitCode(11, contract, treasure);
});

// 12: Fatal error
// NOTE: thrown by TVM in situations deemed impossible

// 13 (actually, -14): Out of gas
it("should test exit code 13", async () => {
const sendResult = await contract.send(
treasure.getSender(),
{ value: toNano("10") },
"13",
);

expect(sendResult.transactions).toHaveTransaction({
from: treasure.address,
to: contract.address,
success: false,
exitCode: -14,
});
await testComputePhaseExitCode(13, contract, treasure);
});

// 14: Virtualization error
// NOTE: Reserved, but never thrown
});

async function testComputePhaseExitCode(
code: number,
contract: SandboxContract<TestContract>,
treasure: SandboxContract<TreasuryContract>,
) {
expect(code).toBeGreaterThanOrEqual(0);
expect(code).toBeLessThan(128);
expect([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13]).toContain(code);
type testedExitCodes =
| "0"
| "1"
| "2"
| "3"
| ExitCode4
| "5"
| "6"
| "7"
| "8"
| "9"
| "10"
| "11"
| "13";

const sendResult = await contract.send(
treasure.getSender(),
{ value: toNano("10") },
code === 4
? {
$$type: "ExitCode4",
val0: BigInt(0),
val1: BigInt(1),
}
: (code.toString(10) as testedExitCodes),
);

expect(sendResult.transactions).toHaveTransaction({
from: treasure.address,
to: contract.address,
success: code === 0 || code === 1 ? true : false,
exitCode: code === 13 ? -14 : code,
});
}
22 changes: 11 additions & 11 deletions src/test/exit-codes/contracts/compute-phase-errors.tact
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ contract ComputePhaseErrorsTester {
} catch (exitCode) {
nativeThrowIf(exitCode, exitCode != targetCode);
}
require(failed == true, "Addition didn't cause an integer overflow");
require(failed, "Addition didn't cause an integer overflow");

// Subtraction
try {
Expand All @@ -53,7 +53,7 @@ contract ComputePhaseErrorsTester {
} catch (exitCode) {
nativeThrowIf(exitCode, exitCode != targetCode);
}
require(failed == true, "Subtraction didn't cause an integer overflow");
require(failed, "Subtraction didn't cause an integer overflow");

// Negation
try {
Expand All @@ -62,7 +62,7 @@ contract ComputePhaseErrorsTester {
} catch (exitCode) {
nativeThrowIf(exitCode, exitCode != targetCode);
}
require(failed == true, "Negation didn't cause an integer overflow");
require(failed, "Negation didn't cause an integer overflow");

// Multiplication
try {
Expand All @@ -71,7 +71,7 @@ contract ComputePhaseErrorsTester {
} catch (exitCode) {
nativeThrowIf(exitCode, exitCode != targetCode);
}
require(failed == true, "Multiplication didn't cause an integer overflow");
require(failed, "Multiplication didn't cause an integer overflow");

// Division
try {
Expand All @@ -80,7 +80,7 @@ contract ComputePhaseErrorsTester {
} catch (exitCode) {
nativeThrowIf(exitCode, exitCode != targetCode);
}
require(failed == true, "Division didn't cause an integer overflow");
require(failed, "Division didn't cause an integer overflow");

// Division by zero
try {
Expand All @@ -89,7 +89,7 @@ contract ComputePhaseErrorsTester {
} catch (exitCode) {
nativeThrowIf(exitCode, exitCode != targetCode);
}
require(failed == true, "Division by zero didn't cause an integer overflow");
require(failed, "Division by zero didn't cause an integer overflow");

// Modulo by zero
try {
Expand All @@ -98,7 +98,7 @@ contract ComputePhaseErrorsTester {
} catch (exitCode) {
nativeThrowIf(exitCode, exitCode != targetCode);
}
require(failed == true, "Modulo by zero didn't cause an integer overflow");
require(failed, "Modulo by zero didn't cause an integer overflow");

// As we got here, everything above caused the target exit code,
// so let's throw it explicitly now for the tests on Blueprint's side
Expand Down Expand Up @@ -141,7 +141,7 @@ contract ComputePhaseErrorsTester {
} catch (exitCode) {
nativeThrowIf(exitCode, exitCode != targetCode);
}
require(failed == true, "1024 bits didn't cause the cell overflow");
require(failed, "1024 bits didn't cause the cell overflow");

// Cell overflow (refs)
try {
Expand All @@ -156,7 +156,7 @@ contract ComputePhaseErrorsTester {
} catch (exitCode) {
nativeThrowIf(exitCode, exitCode != targetCode);
}
require(failed == true, "5 refs didn't cause the cell overflow");
require(failed, "5 refs didn't cause the cell overflow");

// As we got here, everything above caused the target exit code,
// so let's throw it explicitly now for the tests on Blueprint's side
Expand All @@ -176,7 +176,7 @@ contract ComputePhaseErrorsTester {
} catch (exitCode) {
nativeThrowIf(exitCode, exitCode != targetCode);
}
require(failed == true, "Loading 1 bit from an empty Slice didn't cause the cell underflow");
require(failed, "Loading 1 bit from an empty Slice didn't cause the cell underflow");

// Cell underflow (refs)
try {
Expand All @@ -185,7 +185,7 @@ contract ComputePhaseErrorsTester {
} catch (exitCode) {
nativeThrowIf(exitCode, exitCode != targetCode);
}
require(failed == true, "Loading 1 ref from an empty Slice didn't cause the cell underflow");
require(failed, "Loading 1 ref from an empty Slice didn't cause the cell underflow");

// As we got here, everything above caused the target exit code,
// so let's throw it explicitly now for the tests on Blueprint's side
Expand Down
Loading

0 comments on commit b372017

Please sign in to comment.