-
Notifications
You must be signed in to change notification settings - Fork 136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
tests: receiver precedence #1742
Merged
Merged
Changes from 2 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
34a71c6
tests: receivers precedence.
jeshecdom 53e2d7b
Merge branch 'main' into test-receiver-precedence
jeshecdom 9e3c38f
fix: changed strings inside receivers.
jeshecdom b1608b1
feat: Added bounced receivers tests.
jeshecdom 410d9a9
Merge branch 'main' into test-receiver-precedence
jeshecdom 882b2da
feat: Added external receiver tests.
jeshecdom f486d28
refactor: added comment about issue on external receivers with slices.
jeshecdom 7931a55
Prettier pass.
jeshecdom 5717ba3
Merge branch 'main' into test-receiver-precedence
jeshecdom ee51bf4
fix: removed FIXME comments.
jeshecdom 64b2a57
Merge branch 'main' into test-receiver-precedence
jeshecdom efbab25
fix: change expect(var == "string").toBe(true) to expect(var).toBe…
jeshecdom 9d3fa14
docs: explained execution order of receivers.
jeshecdom 5e491c1
refactor: permuted some receivers in contract to match claim in docs …
jeshecdom 2b65f12
feat: added check that calculator transaction exits with code 130 whe…
jeshecdom 37100b5
Merge branch 'main' into test-receiver-precedence
jeshecdom 6e5aab2
chore: lint pass.
jeshecdom File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
message Message { | ||
msg: String; | ||
} | ||
|
||
contract ReceiverTester { | ||
|
||
receiverKind: String = "unknown"; | ||
|
||
receive() { | ||
self.receiverKind = "empty"; | ||
} | ||
|
||
receive("message") { | ||
self.receiverKind = "message"; | ||
} | ||
|
||
receive(msg: String) { | ||
if (msg == "message") { | ||
self.receiverKind = "message_string"; | ||
anton-trunov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} else { | ||
self.receiverKind = "string"; | ||
anton-trunov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
receive(msg: Message) { | ||
self.receiverKind = "Message_struct"; | ||
anton-trunov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
receive(msg: Slice) { | ||
// Drop the op code | ||
msg.loadUint(32); | ||
let m = msg.asString(); | ||
if (m == "message") { | ||
self.receiverKind = "message_slice"; | ||
} else { | ||
self.receiverKind = "slice"; | ||
anton-trunov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
get fun receiverKind(): String { | ||
return self.receiverKind; | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
import { beginCell, Cell, toNano } from "@ton/core"; | ||
import { Blockchain, SandboxContract, TreasuryContract } from "@ton/sandbox"; | ||
import { ReceiverTester } from "./contracts/output/receiver-precedence_ReceiverTester"; | ||
import "@ton/test-utils"; | ||
|
||
describe("receivers-precedence", () => { | ||
let blockchain: Blockchain; | ||
let treasure: SandboxContract<TreasuryContract>; | ||
let contract: SandboxContract<ReceiverTester>; | ||
|
||
beforeEach(async () => { | ||
blockchain = await Blockchain.create(); | ||
blockchain.verbosity.print = false; | ||
treasure = await blockchain.treasury("treasure"); | ||
|
||
contract = blockchain.openContract(await ReceiverTester.fromInit()); | ||
|
||
const deployResult = await contract.send( | ||
treasure.getSender(), | ||
{ value: toNano("10") }, | ||
null, | ||
); | ||
expect(deployResult.transactions).toHaveTransaction({ | ||
from: treasure.address, | ||
to: contract.address, | ||
success: true, | ||
deploy: true, | ||
}); | ||
}); | ||
|
||
it("should implement receivers precedence correctly", async () => { | ||
// Initially, since we sent a deploy message with empty message, the empty receiver executed | ||
const receiver1 = await contract.getReceiverKind(); | ||
expect(receiver1 === "empty").toBe(true); | ||
anton-trunov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Send now a "message" | ||
await contract.send( | ||
treasure.getSender(), | ||
{ value: toNano("10") }, | ||
"message", | ||
); | ||
const receiver2 = await contract.getReceiverKind(); | ||
// Note the receiver "message_string" did not execute | ||
expect(receiver2 === "message").toBe(true); | ||
|
||
// Send now an arbitrary string different from "message" | ||
await contract.send( | ||
treasure.getSender(), | ||
{ value: toNano("10") }, | ||
"msg", | ||
); | ||
const receiver3 = await contract.getReceiverKind(); | ||
// Now, the receiver for general strings executed. | ||
// Note that "message_string" still does not execute, nor the "message_slice" receiver. | ||
expect(receiver3 === "string").toBe(true); | ||
|
||
// Send now a Message (note the capital letter in Message) | ||
await contract.send( | ||
treasure.getSender(), | ||
{ value: toNano("10") }, | ||
{ $$type: "Message", msg: "message" }, | ||
); | ||
const receiver4 = await contract.getReceiverKind(); | ||
// Now, the receiver for Message executed. | ||
expect(receiver4 === "Message_struct").toBe(true); | ||
|
||
// Now, simulate different kinds of messages using slices | ||
|
||
// First, an empty message, which can be simulated with an empty slice | ||
await contract.send( | ||
treasure.getSender(), | ||
{ value: toNano("10") }, | ||
new Cell().asSlice(), | ||
); | ||
// The empty receiver executed | ||
const receiver5 = await contract.getReceiverKind(); | ||
expect(receiver5 === "empty").toBe(true); | ||
|
||
// Send now a "message" simulated as slice | ||
await contract.send( | ||
treasure.getSender(), | ||
{ value: toNano("10") }, | ||
// String receivers are triggered by passing an operation code 0 at the start of the slice | ||
beginCell() | ||
.storeUint(0, 32) | ||
.storeStringTail("message") | ||
.endCell() | ||
.asSlice(), | ||
); | ||
const receiver6 = await contract.getReceiverKind(); | ||
// Note the receiver "message_string" did not execute, nor the receiver "message_slice". | ||
expect(receiver6 === "message").toBe(true); | ||
|
||
// Send now an arbitrary string different from "message" | ||
await contract.send( | ||
treasure.getSender(), | ||
{ value: toNano("10") }, | ||
// String receivers are triggered by passing an operation code 0 at the start of the slice | ||
beginCell() | ||
.storeUint(0, 32) | ||
.storeStringTail("msg") | ||
.endCell() | ||
.asSlice(), | ||
); | ||
const receiver7 = await contract.getReceiverKind(); | ||
// Now, the receiver for general strings executed. | ||
// Note that "message_string" still does not execute. | ||
expect(receiver7 === "string").toBe(true); | ||
|
||
// Note that it is possible to trigger the "message_slice" receiver by passing an operation code different from 0, for example 10. | ||
await contract.send( | ||
treasure.getSender(), | ||
{ value: toNano("10") }, | ||
beginCell() | ||
.storeUint(10, 32) | ||
.storeStringTail("message") | ||
.endCell() | ||
.asSlice(), | ||
); | ||
const receiver8 = await contract.getReceiverKind(); | ||
// Now, the receiver for slices takes the "message" path | ||
expect(receiver8 === "message_slice").toBe(true); | ||
|
||
// Send now an arbitrary slice | ||
await contract.send( | ||
treasure.getSender(), | ||
{ value: toNano("10") }, | ||
beginCell().storeUint(10, 32).endCell().asSlice(), | ||
); | ||
const receiver9 = await contract.getReceiverKind(); | ||
// Now, the receiver for slices executed. | ||
expect(receiver9 === "slice").toBe(true); | ||
|
||
// In all the cases, "message_string" did not execute, as it should be. | ||
}); | ||
}); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.