diff --git a/docs/src/content/docs/ref/core-advanced.mdx b/docs/src/content/docs/ref/core-advanced.mdx index 415e94df1..412367e38 100644 --- a/docs/src/content/docs/ref/core-advanced.mdx +++ b/docs/src/content/docs/ref/core-advanced.mdx @@ -163,7 +163,7 @@ extends fun readForwardFee(self: Context): Int; Extension function for the [`Context{:tact}`](/ref/core-common#context). -Reads [forward fee](https://docs.ton.org/develop/smart-contracts/guidelines/processing) and returns it as [`Int{:tact}`][int] amount of [nanoToncoins][nanotoncoin]. +Reads [forward fee][forward-fee] and returns it as [`Int{:tact}`][int] amount of [nanoToncoins][nanotoncoin]. Usage example: diff --git a/src/stdlib/stdlib.ts b/src/stdlib/stdlib.ts index ded72e632..b65e8b655 100644 --- a/src/stdlib/stdlib.ts +++ b/src/stdlib/stdlib.ts @@ -232,9 +232,26 @@ files["std/config.tact"] = files["std/context.tact"] = "c3RydWN0IENvbnRleHQgewogICAgYm91bmNlZDogQm9vbDsKICAgIHNlbmRlcjogQWRkcmVzczsKICAgIHZhbHVlOiBJbnQ7CiAgICByYXc6IFNsaWNlOwp9CgpAbmFt" + "ZShfX3RhY3RfY29udGV4dF9nZXQpCm5hdGl2ZSBjb250ZXh0KCk6IENvbnRleHQ7CgpAbmFtZShfX3RhY3RfY29udGV4dF9nZXRfc2VuZGVyKQpuYXRpdmUgc2VuZGVy" + - "KCk6IEFkZHJlc3M7Cgphc20gZXh0ZW5kcyBmdW4gcmVhZEZvcndhcmRGZWUoc2VsZjogQ29udGV4dCk6IEludCB7CiAgICBMRE1TR0FERFIKICAgIExER1JBTVMKICAg" + - "IE9ORQogICAgU0RTS0lQRklSU1QKICAgIExER1JBTVMKICAgIExER1JBTVMKICAgIERST1AKICAgIDYgMSBCTEtEUk9QMgogICAgWkVSTwogICAgR0VUT1JJR0lOQUxG" + - "V0RGRUUKfQ=="; + "KCk6IEFkZHJlc3M7CgovLy8gRXh0ZW5zaW9uIGZ1bmN0aW9uIGZvciB0aGUgYENvbnRleHRgIHN0cnVjdHVyZS4KLy8vCi8vLyBSZWFkcyBmb3J3YXJkIGZlZSBhbmQg" + + "cmV0dXJucyBpdCBhcyBgSW50YCBhbW91bnQgb2YgbmFub1RvbmNvaW5zLgovLy8KLy8vIGBgYHRhY3QKLy8vIGZ1biBleGFtcGxlKCkgewovLy8gICAgIGxldCBmd2RG" + + "ZWU6IEludCA9IGNvbnRleHQoKS5yZWFkRm9yd2FyZEZlZSgpOwovLy8gfQovLy8gYGBgCi8vLwovLy8gU2VlOgovLy8gKiBodHRwczovL2RvY3MudGFjdC1sYW5nLm9y" + + "Zy9yZWYvY29yZS1hZHZhbmNlZCNjb250ZXh0cmVhZGZvcndhcmRmZWUKLy8vICogaHR0cHM6Ly9kb2NzLnRhY3QtbGFuZy5vcmcvcmVmL2NvcmUtYWR2YW5jZWQjZ2V0" + + "b3JpZ2luYWxmd2RmZWUKLy8vCmFzbSBleHRlbmRzIGZ1biByZWFkRm9yd2FyZEZlZShzZWxmOiBDb250ZXh0KTogSW50IHsKICAgIC8vIE9ubHkgdGhlIHNlbGYucmF3" + + "IChDb250ZXh0LnJhdykgaXMgaW1wb3J0YW50LAogICAgLy8gc28gYWxsIHRoZSBvdGhlciBmaWVsZHMgYW5kIGxvYWRlZCB2YWx1ZXMgd2lsbCBiZSBkcm9wcGVkIGJ5" + + "IGBCTEtEUk9QMmAKICAgIC8vCiAgICAvLyBDb250ZXh0LnJhdyBzdGFydHMgYXQgdGhlIGRlc3Q6TXNnQWRkcmVzc0ludCwgZm9sbG93aW5nIHRoaXMgVEwtQiBzY2hl" + + "bWU6CiAgICAvLyBpbnRfbXNnX2luZm8kMAogICAgLy8gICBpaHJfZGlzYWJsZWQ6Qm9vbAogICAgLy8gICBib3VuY2U6Qm9vbAogICAgLy8gICBib3VuY2VkOkJvb2wK" + + "ICAgIC8vICAgc3JjOk1zZ0FkZHJlc3MKICAgIC8vICAgZGVzdDpNc2dBZGRyZXNzSW50IOKGkCBoZXJlIGlzIHRoZSBzdGFydAogICAgLy8gICB2YWx1ZTpDdXJyZW5j" + + "eUNvbGxlY3Rpb24KICAgIC8vICAgaWhyX2ZlZTpHcmFtcwogICAgLy8gICBmd2RfZmVlOkdyYW1zCiAgICAvLyAgIGNyZWF0ZWRfbHQ6dWludDY0CiAgICAvLyAgIGNy" + + "ZWF0ZWRfYXQ6dWludDMyCiAgICAvLyA9IENvbW1vbk1zZ0luZm9SZWxheGVkOwoKICAgIExETVNHQUREUiAgIC8vIGxvYWQgZGVzdDpNc2dBZGRyZXNzSW50CiAgICBM" + + "REdSQU1TICAgICAvLyBsb2FkIHZhbHVlOkN1cnJlbmN5Q29sbGVjdGlvbgogICAgT05FCiAgICBTRFNLSVBGSVJTVCAvLyBza2lwIGV4dHJhIGN1cnJlbmN5IGNvbGxl" + + "Y3Rpb24KICAgIExER1JBTVMgICAgIC8vIGxvYWQgaWhyX2ZlZQogICAgTERHUkFNUyAgICAgLy8gbG9hZCBmd2RfZmVlLCB3ZSdsbCBiZSB1c2luZyB0aGlzIQogICAg" + + "RFJPUCAgICAgICAgLy8gZHJvcCByZW1haW5pbmcgU2xpY2UgKHdpdGggY3JlYXRlZF9sdCBhbmQgY3JlYXRlZF9hdCkKCiAgICAvLyBUaGVyZSBhcmUgNyBlbnRyaWVz" + + "IG9uIHRoZSBzdGFjayDigJQgZmlyc3QgMyBmaWVsZHMgb2YgQ29udGV4dCBwbHVzIDQgbG9hZGVkIG9uZXMuCiAgICAvLyBUaGUgdG9wbW9zdCBpcyBmd2RfZmVlLCB3" + + "aGljaCBpcyB0aGUgb25seSBvbmUgd2UncmUgYWZ0ZXIsIHNvIGxldCdzIGRyb3AgNiBlbnRyaWVzIGJlbG93OgogICAgNiAxIEJMS0RST1AyIC8vIGRyb3AgdGhlIGxv" + + "YWRlZCB2YWx1ZXMgYXMgd2VsbCBhcyB0aGUgZmlyc3QgMyBmaWVsZHMgb2YgQ29udGV4dAoKICAgIFpFUk8gICAgICAgICAgICAgIC8vIG5vdCBtYXN0ZXJjaGFpbgog" + + "ICAgR0VUT1JJR0lOQUxGV0RGRUUgLy8gKGZ3ZF9mZWUgKiAyXjE2KSAvIGZpcnN0X2ZyYWMsIHdoZXJlCiAgICAgICAgICAgICAgICAgICAgICAvLyBmaXJzdF9mcmFj" + + "IGlzIGEgdmFsdWUgbGlzdGVkIGluIGNvbmZpZyBwYXJhbSAyNQogICAgICAgICAgICAgICAgICAgICAgLy8gb2YgdGhlIGJsb2NrY2hhaW46IGh0dHBzOi8vdG9uc2Nh" + + "bi5vcmcvY29uZmlnIzI1Cn0K"; files["std/contract.tact"] = "c3RydWN0IFN0YXRlSW5pdCB7CiAgICBjb2RlOiBDZWxsOwogICAgZGF0YTogQ2VsbDsKfQoKQG5hbWUoX190YWN0X2NvbXB1dGVfY29udHJhY3RfYWRkcmVzcykKbmF0" + "aXZlIGNvbnRyYWN0QWRkcmVzc0V4dChjaGFpbjogSW50LCBjb2RlOiBDZWxsLCBkYXRhOiBDZWxsKTogQWRkcmVzczsKCmlubGluZSBmdW4gY29udHJhY3RBZGRyZXNz" + @@ -400,29 +417,50 @@ files["std/send.tact"] = "b25zdCBTZW5kUGF5R2FzU2VwYXJhdGVseTogSW50ID0gMTsKY29uc3QgU2VuZERlc3Ryb3lJZlplcm86IEludCA9IDMyOwpjb25zdCBTZW5kQm91bmNlSWZBY3Rpb25G" + "YWlsOiBJbnQgPSAxNjsKY29uc3QgU2VuZE9ubHlFc3RpbWF0ZUZlZTogSW50ID0gMTAyNDsKCnN0cnVjdCBTZW5kUGFyYW1ldGVycyB7CiAgICBib3VuY2U6IEJvb2wg" + "PSB0cnVlOwogICAgdG86IEFkZHJlc3M7CiAgICB2YWx1ZTogSW50OwogICAgbW9kZTogSW50ID0gMDsKICAgIGJvZHk6IENlbGw/ID0gbnVsbDsKICAgIGNvZGU6IENl" + - "bGw/ID0gbnVsbDsKICAgIGRhdGE6IENlbGw/ID0gbnVsbDsKfQoKZnVuIHNlbmQocGFyYW1zOiBTZW5kUGFyYW1ldGVycyk6IEludCB7IC8vIHJldHVybnMgZm9yd2Fy" + - "ZCBmZWUKICAgIGxldCBiOiBCdWlsZGVyID0gYmVnaW5DZWxsKCk7CiAgICBiID0gYi5zdG9yZUludCgxLCAyKTsgLy8gaW50ZXJuYWxfbWVzc2FnZSArIGloZF9kaXNh" + - "YmxlZAogICAgYiA9IGIuc3RvcmVCb29sKHBhcmFtcy5ib3VuY2UpOyAvLyBib3VuY2UKICAgIGIgPSBiLnN0b3JlSW50KDAsIDMpOyAvLyBib3VuY2VkICsgZnJvbQog" + - "ICAgYiA9IGIuc3RvcmVBZGRyZXNzKHBhcmFtcy50byk7IC8vIFRvCiAgICBiID0gYi5zdG9yZUNvaW5zKHBhcmFtcy52YWx1ZSk7IC8vIFZhbHVlCiAgICBiID0gYi5z" + - "dG9yZUludCgwLCAxICsgNCArIDQgKyA2NCArIDMyKTsgLy8gY3VycmVuY3lfY29sbGVjdGlvbiArIElIUiBmZWVzICsgRndkIGZlZXMgKyBDcmVhdGVkTFQgKyBDcmVh" + - "dGVkQXQKCiAgICAvLyBTdGF0ZWluaXQKICAgIGlmIChwYXJhbXMuY29kZSAhPSBudWxsIHx8IHBhcmFtcy5kYXRhICE9IG51bGwpIHsKICAgICAgICBiID0gYi5zdG9y" + - "ZUJvb2wodHJ1ZSk7IC8vIFN0YXRlIGluaXQKCiAgICAgICAgLy8gQXNzZW1ibGUgc3RhdGUgaW5pdCBjZWxsCiAgICAgICAgbGV0IGJjOiBCdWlsZGVyID0gYmVnaW5D" + - "ZWxsKCk7CiAgICAgICAgYmMgPSBiYy5zdG9yZUJvb2woZmFsc2UpOyAvLyBTcGxpdERlcHRoCiAgICAgICAgYmMgPSBiYy5zdG9yZUJvb2woZmFsc2UpOyAvLyBUaWNr" + - "VG9jawogICAgICAgIGlmIChwYXJhbXMuY29kZSAhPSBudWxsKSB7CiAgICAgICAgICAgIGJjID0gYmMuc3RvcmVCb29sKHRydWUpOyAvLyBDb2RlIHByZXNlbmNlCiAg" + - "ICAgICAgICAgIGJjID0gYmMuc3RvcmVSZWYocGFyYW1zLmNvZGUhISk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgYmMgPSBiYy5zdG9yZUJvb2woZmFsc2Up" + - "OyAvLyBDb2RlIHByZXNlbmNlCiAgICAgICAgfQogICAgICAgIGlmIChwYXJhbXMuZGF0YSAhPSBudWxsKSB7CiAgICAgICAgICAgIGJjID0gYmMuc3RvcmVCb29sKHRy" + - "dWUpOyAvLyBEYXRhIHByZXNlbmNlCiAgICAgICAgICAgIGJjID0gYmMuc3RvcmVSZWYocGFyYW1zLmRhdGEhISk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAg" + - "YmMgPSBiYy5zdG9yZUJvb2woZmFsc2UpOyAvLyBEYXRhIHByZXNlbmNlCiAgICAgICAgfQogICAgICAgIGJjID0gYmMuc3RvcmVCb29sKGZhbHNlKTsgLy8gTGlicmFy" + - "eQoKICAgICAgICBiID0gYi5zdG9yZUJvb2wodHJ1ZSk7IC8vIFN0b3JlIGFzIHJlZgogICAgICAgIGIgPSBiLnN0b3JlUmVmKGJjLmVuZENlbGwoKSk7CiAgICB9IGVs" + - "c2UgewogICAgICAgIGIgPSBiLnN0b3JlQm9vbChmYWxzZSk7IC8vIE5vIHN0YXRlIGluaXQKICAgIH0KCiAgICAvLyBCb2R5CiAgICBsZXQgYm9keTogQ2VsbD8gPSBw" + - "YXJhbXMuYm9keTsKICAgIGlmIChib2R5ICE9IG51bGwpIHsKICAgICAgICBiID0gYi5zdG9yZUJvb2wodHJ1ZSk7CiAgICAgICAgYiA9IGIuc3RvcmVSZWYoYm9keSEh" + - "KTsKICAgIH0gZWxzZSB7CiAgICAgICAgYiA9IGIuc3RvcmVCb29sKGZhbHNlKTsgLy8gTm8gYm9keQogICAgfQoKICAgIC8vIFNlbmQKICAgIGxldCBjOiBDZWxsID0g" + - "Yi5lbmRDZWxsKCk7CiAgICByZXR1cm4gbmF0aXZlU2VuZE1lc3NhZ2VSZXR1cm5Gb3J3YXJkRmVlKGMsIHBhcmFtcy5tb2RlKTsKfQoKaW5saW5lIGZ1biBlbWl0KGJv" + - "ZHk6IENlbGwpIHsKICAgIC8vIGV4dF9vdXRfbXNnX2luZm8kMTEgc3JjOk1zZ0FkZHJlc3NJbnQgZGVzdDpNc2dBZGRyZXNzRXh0IGNyZWF0ZWRfbHQ6dWludDY0IGNy" + - "ZWF0ZWRfYXQ6dWludDMyCiAgICAvLyAgICAgICAgICAgICAgICAgICAgIG1heWJlOiBzdGF0ZUluaXQgKGZhbHNlKSBib2R5UmVmOiBib29sICh0cnVlKQogICAgbGV0" + - "IGM6IENlbGwgPSBiZWdpbkNlbGwoKQogICAgICAgIC5zdG9yZVVpbnQoMTUyMTE4MDcyMDI3Mzg3NTI4MTc5NjA0Mzg0NjQ1MTMsIDEwNCkKICAgICAgICAuc3RvcmVS" + - "ZWYoYm9keSkKICAgICAgICAuZW5kQ2VsbCgpOwogICAgbmF0aXZlU2VuZE1lc3NhZ2UoYywgMCk7Cn0KCmFzbSBmdW4gYWNjZXB0TWVzc2FnZSgpIHsgQUNDRVBUIH0K" + - "CmFzbSBmdW4gY29tbWl0KCkgeyBDT01NSVQgfQo="; + "bGw/ID0gbnVsbDsKICAgIGRhdGE6IENlbGw/ID0gbnVsbDsKfQoKCi8vLyBHbG9iYWwgZnVuY3Rpb24uIFF1ZXVlcyB0aGUgbWVzc2FnZSB0byBiZSBzZW50IHVzaW5n" + + "IGEgYFNlbmRQYXJhbWV0ZXJzYCBTdHJ1Y3QuCi8vLwovLy8gQXR0ZW1wdHMgdG8gcXVldWUgbW9yZSB0aGFuIDI1NSBtZXNzYWdlcyB0aHJvdyBhbiBleGNlcHRpb24g" + + "d2l0aCBhbiBleGl0IGNvZGUgMzM6IGBBY3Rpb24gbGlzdCBpcyB0b28gbG9uZ2AuCi8vLwovLy8gYGBgdGFjdAovLy8gZnVuIGV4YW1wbGUoKSB7Ci8vLyAgICAgc2Vu" + + "ZChTZW5kUGFyYW1ldGVyc3sKLy8vICAgICAgICAgdG86IHNlbmRlcigpLCAgICAvLyBiYWNrIHRvIHRoZSBzZW5kZXIsCi8vLyAgICAgICAgIHZhbHVlOiB0b24oIjEi" + + "KSwgLy8gd2l0aCAxIFRvbmNvaW4gKDFfMDAwXzAwMF8wMDAgbmFub1RvbmNvaW4pLAovLy8gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFuZCBubyBtZXNzYWdl" + + "IGJvZHkKLy8vICAgICB9KTsKLy8vIH0KLy8vIGBgYAovLy8KLy8vIFNlZTogaHR0cHM6Ly9kb2NzLnRhY3QtbGFuZy5vcmcvcmVmL2NvcmUtY29tbW9uI3NlbmQKLy8v" + + "CmFzbSBmdW4gc2VuZChwYXJhbXM6IFNlbmRQYXJhbWV0ZXJzKSB7CiAgICAvLyBJbnN0cnVjdGlvbnMgYXJlIGdyb3VwZWQsIGFuZCB0aGUgc3RhY2sgc3RhdGVzIHRo" + + "ZXkgcHJvZHVjZSBhcyBhIGdyb3VwIGFyZSBzaG93biByaWdodCBhZnRlci4KICAgIC8vIEluIHRoZSBlbmQsIG91ciBtZXNzYWdlIENlbGwgc2hvdWxkIGhhdmUgdGhl" + + "IGZvbGxvd2luZyBUTC1CIHN0cnVjdHVyZToKICAgIC8vIG1lc3NhZ2UkXyB7WDpUeXBlfQogICAgLy8gICBpbmZvOkNvbW1vbk1zZ0luZm9SZWxheGVkCiAgICAvLyAg" + + "IGluaXQ6KE1heWJlIChFaXRoZXIgU3RhdGVJbml0IF5TdGF0ZUluaXQpKQogICAgLy8gICBib2R5OihFaXRoZXIgWCBeWCkKICAgIC8vID0gTWVzc2FnZVJlbGF4ZWQg" + + "WDsKCiAgICAvLyBHcm91cCAxOiBSZWFycmFuZ2VtZW50cwogICAgMyA0IEJMS1NXQVAKICAgIHMyIFhDSEcwCiAgICAvLyDihpIgU3RhY2sgc3RhdGUKICAgIC8vIHMw" + + "OiBgcGFyYW1zLmJvdW5jZWAKICAgIC8vIHMxOiBgcGFyYW1zLnRvYAogICAgLy8gczI6IGBwYXJhbXMudmFsdWVgCiAgICAvLyBzMzogYHBhcmFtcy5kYXRhYAogICAg" + + "Ly8gczQ6IGBwYXJhbXMuY29kZWAKICAgIC8vIHM1OiBgcGFyYW1zLmJvZHlgCiAgICAvLyBzNjogYHBhcmFtcy5tb2RlYAogICAgLy8gRm9yIGJyZXZpdHksIHRoZSAi" + + "cGFyYW1zIiBwcmVmaXggd2lsbCBiZSBvbWl0dGVkIGZyb20gbm93IG9uLgoKICAgIC8vIEdyb3VwIDI6IFN0b3JpbmcgdGhlIGBib3VuY2VgLCBgdG9gIGFuZCBgdmFs" + + "dWVgIGludG8gYSBCdWlsZGVyCiAgICBORVdDCiAgICBiezAxfSBTVFNMSUNFQ09OU1QgIC8vIHN0b3JlIHRhZyA9ICQwLCBpaHJfZGlzYWJsZWQgPSB0cnVlCiAgICAx" + + "IFNUSSAgICAgICAgICAgICAgIC8vIHN0b3JlIGBib3VuY2VgCiAgICBiezAwMH0gU1RTTElDRUNPTlNUIC8vIHN0b3JlIHNyY19hZGRyID0gYWRkcl9ub25lCiAgICBT" + + "VFNMSUNFICAgICAgICAgICAgIC8vIHN0b3JlIGB0b2AKICAgIFNXQVAKICAgIFNUR1JBTVMgICAgICAgICAgICAgLy8gc3RvcmUgbmFub3RvbnMKICAgIDEwNSBQVVNI" + + "SU5UICAgICAgICAgLy8gMSArIDQgKyA0ICsgNjQgKyAzMgogICAgU1RaRVJPRVMgICAgICAgICAgICAvLyBzdG9yZSBjdXJyZW5jeV9jb2xsZWN0aW9uLCBpaHJfZmVl" + + "LCBmd2RfZmVlLCBjcmVhdGVkX2x0IGFuZCBjcmVhdGVkX2F0CiAgICAvLyDihpIgU3RhY2sgc3RhdGUKICAgIC8vIHMwOiBCdWlsZGVyCiAgICAvLyBzMTogYGRhdGFg" + + "CiAgICAvLyBzMjogYGNvZGVgCiAgICAvLyBzMzogYGJvZHlgCiAgICAvLyBzNDogYG1vZGVgCgogICAgLy8gR3JvdXAgMzogUGxhY2luZyB0aGUgQnVpbGRlciBhZnRl" + + "ciBjb2RlIGFuZCBkYXRhLCB0aGVuIGNoZWNraW5nIHRob3NlIGZvciBudWxsYWJpbGl0eQogICAgczIgWENIRzAKICAgIERVUDIKICAgIElTTlVMTAogICAgU1dBUAog" + + "ICAgSVNOVUxMCiAgICBNVUwgLy8gbm90ZSB0aGF0IC0xICogLTEgd3JhcHMgYmFjayB0byAtMQogICAgLy8g4oaSIFN0YWNrIHN0YXRlCiAgICAvLyBzMDogLTEgKHRy" + + "dWUpIGlmIGBkYXRhYCBhbmQgYGNvZGVgIGFyZSBib3RoIG51bGwsIDAgKGZhbHNlKSBvdGhlcndpc2UKICAgIC8vIHMxOiBgY29kZWAKICAgIC8vIHMyOiBgZGF0YWAK" + + "ICAgIC8vIHMzOiBCdWlsZGVyCiAgICAvLyBzNDogYGJvZHlgCiAgICAvLyBzNTogYG1vZGVgCgogICAgLy8gR3JvdXAgNDogTGVmdCBicmFuY2ggb2YgdGhlIElGRUxT" + + "RSwgZXhlY3V0ZWQgaWYgczAgaXMgLTEgKHRydWUpCiAgICA8ewogICAgICAgIERST1AyIC8vIGRyb3AgYGRhdGFgIGFuZCBgY29kZWAsIHNpbmNlIGVpdGhlciBvZiB0" + + "aG9zZSBpcyBudWxsCiAgICAgICAgTlVMTCAgLy8gcHVzaCBhIHNpbmdsZSBudWxsCiAgICAgICAgU1dBUCAgLy8gcGxhY2UgQnVpbGRlciBvbiB0b3AKICAgIH0+IFBV" + + "U0hDT05UCgogICAgLy8gR3JvdXAgNDogUmlnaHQgYnJhbmNoIG9mIHRoZSBJRkVMU0UsIGV4ZWN1dGVkIGlmIHMwIGlzIDAgKGZhbHNlKQogICAgPHsKICAgICAgICAv" + + "LyBfIHNwbGl0X2RlcHRoOihNYXliZSAoIyMgNSkpCiAgICAgICAgLy8gICBzcGVjaWFsOihNYXliZSBUaWNrVG9jaykKICAgICAgICAvLyAgIGNvZGU6KE1heWJlIF5D" + + "ZWxsKQogICAgICAgIC8vICAgZGF0YTooTWF5YmUgXkNlbGwpCiAgICAgICAgLy8gICBsaWJyYXJ5OihNYXliZSBeQ2VsbCkKICAgICAgICAvLyA9IFN0YXRlSW5pdDsK" + + "ICAgICAgICBORVdDICAgICAgICAgICAgICAgLy8gc3RhcnQgY29tcG9zaW5nIFN0YXRlSW5pdAogICAgICAgIGJ7MDB9IFNUU0xJQ0VDT05TVCAvLyBzcGxpdF9kZXB0" + + "aCBhbmQgc3BlY2lhbAogICAgICAgIFNURElDVCAgICAgICAgICAgICAvLyBzdG9yZSBjb2RlCiAgICAgICAgU1RESUNUICAgICAgICAgICAgIC8vIHN0b3JlIGRhdGEK" + + "ICAgICAgICBiezB9IFNUU0xJQ0VDT05TVCAgLy8gc3RvcmUgbGlicmFyeQogICAgICAgIEVOREMgICAgICAgICAgICAgICAvLyBlbmQgY29tcG9zaW5nIFN0YXRlSW5p" + + "dAogICAgICAgIFNXQVAgICAgICAgICAgICAgICAvLyBwbGFjZSBCdWlsZGVyIG9uIHRvcAogICAgICAgIGJ7MX0gU1RTTElDRUNPTlNUICAvLyBhbiBleHRyYSBiaXQg" + + "Zm9yIHN0b3JpbmcgU3RhdGVJbml0IGFzIHJlZgogICAgfT4gUFVTSENPTlQKCiAgICAvLyBHcm91cCA0OiBJRkVMU0UgdGhhdCBkb2VzIHRoZSBicmFuY2hpbmcgc2hv" + + "d24gYWJvdmUKICAgIElGRUxTRQogICAgLy8g4oaSIFN0YWNrIHN0YXRlCiAgICAvLyBzMDogQnVpbGRlcgogICAgLy8gczE6IG51bGwgb3IgU3RhdGVJbml0CiAgICAv" + + "LyBzMjogYGJvZHlgCiAgICAvLyBzMzogYG1vZGVgCgogICAgLy8gR3JvdXAgNTogRmluYWxpemluZyB0aGUgbWVzc2FnZQogICAgU1RESUNUIC8vIHN0b3JlIFN0YXRl" + + "SW5pdAogICAgU1RESUNUIC8vIHN0b3JlIGBib2R5YCBhcyByZWYgd2l0aCBhbiBleHRyYSBNYXliZSBiaXQsIHNpbmNlIGBib2R5YCBtaWdodCBiZSBudWxsCiAgICBF" + + "TkRDCiAgICAvLyDihpIgU3RhY2sgc3RhdGUKICAgIC8vIHMwOiBDZWxsCiAgICAvLyBzMTogYG1vZGVgCgogICAgLy8gR3JvdXAgNjogU2VuZGluZyB0aGUgbWVzc2Fn" + + "ZSwgd2l0aCBgbW9kZWAgb24gdG9wCiAgICBTV0FQCiAgICBTRU5EUkFXTVNHIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS90YWN0LWxhbmcvdGFjdC9pc3N1ZXMvMTU1OAp9" + + "CgppbmxpbmUgZnVuIGVtaXQoYm9keTogQ2VsbCkgewogICAgLy8gZXh0X291dF9tc2dfaW5mbyQxMSBzcmM6TXNnQWRkcmVzc0ludCBkZXN0Ok1zZ0FkZHJlc3NFeHQg" + + "Y3JlYXRlZF9sdDp1aW50NjQgY3JlYXRlZF9hdDp1aW50MzIKICAgIC8vICAgICAgICAgICAgICAgICAgICAgbWF5YmU6IHN0YXRlSW5pdCAoZmFsc2UpIGJvZHlSZWY6" + + "IGJvb2wgKHRydWUpCiAgICBsZXQgYzogQ2VsbCA9IGJlZ2luQ2VsbCgpCiAgICAgICAgLnN0b3JlVWludCgxNTIxMTgwNzIwMjczODc1MjgxNzk2MDQzODQ2NDUxMywg" + + "MTA0KQogICAgICAgIC5zdG9yZVJlZihib2R5KQogICAgICAgIC5lbmRDZWxsKCk7CiAgICBuYXRpdmVTZW5kTWVzc2FnZShjLCAwKTsKfQoKYXNtIGZ1biBhY2NlcHRN" + + "ZXNzYWdlKCkgeyBBQ0NFUFQgfQoKYXNtIGZ1biBjb21taXQoKSB7IENPTU1JVCB9Cg=="; files["std/text.tact"] = "Ly8KLy8gU3RyaW5nIGJ1aWxkZXIKLy8KCkBuYW1lKF9fdGFjdF9zdHJpbmdfYnVpbGRlcl9zdGFydF9zdHJpbmcpCm5hdGl2ZSBiZWdpblN0cmluZygpOiBTdHJpbmdC" + "dWlsZGVyOwoKQG5hbWUoX190YWN0X3N0cmluZ19idWlsZGVyX3N0YXJ0X2NvbW1lbnQpCm5hdGl2ZSBiZWdpbkNvbW1lbnQoKTogU3RyaW5nQnVpbGRlcjsKCkBuYW1l" + diff --git a/src/stdlib/stdlib/std/context.tact b/src/stdlib/stdlib/std/context.tact index 938872797..6cd82b409 100644 --- a/src/stdlib/stdlib/std/context.tact +++ b/src/stdlib/stdlib/std/context.tact @@ -11,15 +11,52 @@ native context(): Context; @name(__tact_context_get_sender) native sender(): Address; +/// Extension function for the `Context` structure. +/// +/// Reads forward fee and returns it as `Int` amount of nanoToncoins. +/// +/// ```tact +/// fun example() { +/// let fwdFee: Int = context().readForwardFee(); +/// } +/// ``` +/// +/// See: +/// * https://docs.tact-lang.org/ref/core-advanced#contextreadforwardfee +/// * https://docs.tact-lang.org/ref/core-advanced#getoriginalfwdfee +/// asm extends fun readForwardFee(self: Context): Int { - LDMSGADDR - LDGRAMS + // Only the self.raw (Context.raw) is important, + // so all the other fields and loaded values will be dropped by `BLKDROP2` + // + // Context.raw starts at the dest:MsgAddressInt, following this TL-B scheme: + // int_msg_info$0 + // ihr_disabled:Bool + // bounce:Bool + // bounced:Bool + // src:MsgAddress + // dest:MsgAddressInt ← here is the start + // value:CurrencyCollection + // ihr_fee:Grams + // fwd_fee:Grams + // created_lt:uint64 + // created_at:uint32 + // = CommonMsgInfoRelaxed; + + LDMSGADDR // load dest:MsgAddressInt + LDGRAMS // load value:CurrencyCollection ONE - SDSKIPFIRST - LDGRAMS - LDGRAMS - DROP - 6 1 BLKDROP2 - ZERO - GETORIGINALFWDFEE -} \ No newline at end of file + SDSKIPFIRST // skip extra currency collection + LDGRAMS // load ihr_fee + LDGRAMS // load fwd_fee, we'll be using this! + DROP // drop remaining Slice (with created_lt and created_at) + + // There are 7 entries on the stack — first 3 fields of Context plus 4 loaded ones. + // The topmost is fwd_fee, which is the only one we're after, so let's drop 6 entries below: + 6 1 BLKDROP2 // drop the loaded values as well as the first 3 fields of Context + + ZERO // not masterchain + GETORIGINALFWDFEE // (fwd_fee * 2^16) / first_frac, where + // first_frac is a value listed in config param 25 + // of the blockchain: https://tonscan.org/config#25 +} diff --git a/src/stdlib/stdlib/std/send.tact b/src/stdlib/stdlib/std/send.tact index 276814c43..3d16382d5 100644 --- a/src/stdlib/stdlib/std/send.tact +++ b/src/stdlib/stdlib/std/send.tact @@ -21,55 +21,121 @@ struct SendParameters { data: Cell? = null; } -fun send(params: SendParameters): Int { // returns forward fee - let b: Builder = beginCell(); - b = b.storeInt(1, 2); // internal_message + ihd_disabled - b = b.storeBool(params.bounce); // bounce - b = b.storeInt(0, 3); // bounced + from - b = b.storeAddress(params.to); // To - b = b.storeCoins(params.value); // Value - b = b.storeInt(0, 1 + 4 + 4 + 64 + 32); // currency_collection + IHR fees + Fwd fees + CreatedLT + CreatedAt - - // Stateinit - if (params.code != null || params.data != null) { - b = b.storeBool(true); // State init - - // Assemble state init cell - let bc: Builder = beginCell(); - bc = bc.storeBool(false); // SplitDepth - bc = bc.storeBool(false); // TickTock - if (params.code != null) { - bc = bc.storeBool(true); // Code presence - bc = bc.storeRef(params.code!!); - } else { - bc = bc.storeBool(false); // Code presence - } - if (params.data != null) { - bc = bc.storeBool(true); // Data presence - bc = bc.storeRef(params.data!!); - } else { - bc = bc.storeBool(false); // Data presence - } - bc = bc.storeBool(false); // Library - - b = b.storeBool(true); // Store as ref - b = b.storeRef(bc.endCell()); - } else { - b = b.storeBool(false); // No state init - } - - // Body - let body: Cell? = params.body; - if (body != null) { - b = b.storeBool(true); - b = b.storeRef(body!!); - } else { - b = b.storeBool(false); // No body - } - - // Send - let c: Cell = b.endCell(); - return nativeSendMessageReturnForwardFee(c, params.mode); + +/// Global function. Queues the message to be sent using a `SendParameters` Struct. +/// +/// Attempts to queue more than 255 messages throw an exception with an exit code 33: `Action list is too long`. +/// +/// ```tact +/// fun example() { +/// send(SendParameters{ +/// to: sender(), // back to the sender, +/// value: ton("1"), // with 1 Toncoin (1_000_000_000 nanoToncoin), +/// // and no message body +/// }); +/// } +/// ``` +/// +/// See: https://docs.tact-lang.org/ref/core-common#send +/// +asm fun send(params: SendParameters) { + // Instructions are grouped, and the stack states they produce as a group are shown right after. + // In the end, our message Cell should have the following TL-B structure: + // message$_ {X:Type} + // info:CommonMsgInfoRelaxed + // init:(Maybe (Either StateInit ^StateInit)) + // body:(Either X ^X) + // = MessageRelaxed X; + + // Group 1: Rearrangements + 3 4 BLKSWAP + s2 XCHG0 + // → Stack state + // s0: `params.bounce` + // s1: `params.to` + // s2: `params.value` + // s3: `params.data` + // s4: `params.code` + // s5: `params.body` + // s6: `params.mode` + // For brevity, the "params" prefix will be omitted from now on. + + // Group 2: Storing the `bounce`, `to` and `value` into a Builder + NEWC + b{01} STSLICECONST // store tag = $0, ihr_disabled = true + 1 STI // store `bounce` + b{000} STSLICECONST // store src_addr = addr_none + STSLICE // store `to` + SWAP + STGRAMS // store nanotons + 105 PUSHINT // 1 + 4 + 4 + 64 + 32 + STZEROES // store currency_collection, ihr_fee, fwd_fee, created_lt and created_at + // → Stack state + // s0: Builder + // s1: `data` + // s2: `code` + // s3: `body` + // s4: `mode` + + // Group 3: Placing the Builder after code and data, then checking those for nullability + s2 XCHG0 + DUP2 + ISNULL + SWAP + ISNULL + MUL // note that -1 * -1 wraps back to -1 + // → Stack state + // s0: -1 (true) if `data` and `code` are both null, 0 (false) otherwise + // s1: `code` + // s2: `data` + // s3: Builder + // s4: `body` + // s5: `mode` + + // Group 4: Left branch of the IFELSE, executed if s0 is -1 (true) + <{ + DROP2 // drop `data` and `code`, since either of those is null + NULL // push a single null + SWAP // place Builder on top + }> PUSHCONT + + // Group 4: Right branch of the IFELSE, executed if s0 is 0 (false) + <{ + // _ split_depth:(Maybe (## 5)) + // special:(Maybe TickTock) + // code:(Maybe ^Cell) + // data:(Maybe ^Cell) + // library:(Maybe ^Cell) + // = StateInit; + NEWC // start composing StateInit + b{00} STSLICECONST // split_depth and special + STDICT // store code + STDICT // store data + b{0} STSLICECONST // store library + ENDC // end composing StateInit + SWAP // place Builder on top + b{1} STSLICECONST // an extra bit for storing StateInit as ref + }> PUSHCONT + + // Group 4: IFELSE that does the branching shown above + IFELSE + // → Stack state + // s0: Builder + // s1: null or StateInit + // s2: `body` + // s3: `mode` + + // Group 5: Finalizing the message + STDICT // store StateInit + STDICT // store `body` as ref with an extra Maybe bit, since `body` might be null + ENDC + // → Stack state + // s0: Cell + // s1: `mode` + + // Group 6: Sending the message, with `mode` on top + SWAP + SENDRAWMSG // https://github.com/tact-lang/tact/issues/1558 } inline fun emit(body: Cell) { diff --git a/src/test/benchmarks/jetton/results.json b/src/test/benchmarks/jetton/results.json index 3d03c2297..510a24ed6 100644 --- a/src/test/benchmarks/jetton/results.json +++ b/src/test/benchmarks/jetton/results.json @@ -48,11 +48,17 @@ "burn": "17686", "discovery": "11039" }, + { + "label": "1.5.3 with optimized send()", + "transfer": "21464", + "burn": "16029", + "discovery": "10093" + }, { "label": "master", - "transfer": "25860", - "burn": "17686", - "discovery": "11039" + "transfer": "21402", + "burn": "16029", + "discovery": "10085" } ] }