runtime_errors.rs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. // SPDX-License-Identifier: Apache-2.0
  2. use crate::{build_solidity, BorshToken};
  3. use num_bigint::BigInt;
  4. #[test]
  5. fn runtime_errors() {
  6. let mut vm = build_solidity(
  7. r#"
  8. contract RuntimeErrors {
  9. bytes b = hex"0000_00fa";
  10. uint256[] arr;
  11. child public c;
  12. child public c2;
  13. constructor() {}
  14. function print_test(int8 num) public returns (int8) {
  15. print("Hello world!");
  16. require(num > 10, "sesa");
  17. assert(num > 10);
  18. int8 ovf = num + 120;
  19. print("x = {}".format(ovf));
  20. return ovf;
  21. }
  22. function math_overflow(int8 num) public returns (int8) {
  23. int8 ovf = num + 120;
  24. print("x = {}".format(ovf));
  25. return ovf;
  26. }
  27. function require_test(int256 num) public returns (int8) {
  28. require(num > 10, "sesa");
  29. return 0;
  30. }
  31. // assert failure
  32. function assert_test(int256 num) public returns (int8) {
  33. assert(num > 10);
  34. return 0;
  35. }
  36. // storage index out of bounds
  37. function set_storage_bytes() public returns (bytes) {
  38. bytes sesa = new bytes(1);
  39. b[5] = sesa[0];
  40. return sesa;
  41. }
  42. // storage array index out of bounds
  43. function get_storage_bytes() public returns (bytes) {
  44. bytes sesa = new bytes(1);
  45. sesa[0] = b[5];
  46. return sesa;
  47. }
  48. // pop from empty storage array
  49. function pop_empty_storage() public {
  50. arr.pop();
  51. }
  52. // contract creation failed
  53. function create_child() public {
  54. address a = address(0);
  55. c = new child{address: a}();
  56. //c2 = new child();
  57. uint128 x = address(this).balance;
  58. //print("sesa");
  59. print("x = {}".format(x));
  60. }
  61. function i_will_revert() public {
  62. revert();
  63. }
  64. function write_integer_failure(uint256 buf_size) public {
  65. bytes smol_buf = new bytes(buf_size);
  66. smol_buf.writeUint32LE(350, 20);
  67. }
  68. function write_bytes_failure(uint256 buf_size) public {
  69. bytes data = new bytes(10);
  70. bytes smol_buf = new bytes(buf_size);
  71. smol_buf.writeBytes(data, 0);
  72. }
  73. function read_integer_failure(uint32 offset) public {
  74. bytes smol_buf = new bytes(1);
  75. smol_buf.readUint16LE(offset);
  76. }
  77. // truncated type overflows
  78. function trunc_failure(uint256 input) public returns (uint256[]) {
  79. uint256[] a = new uint256[](input);
  80. return a;
  81. }
  82. function out_of_bounds(uint256 input) public returns (uint256) {
  83. uint256[] a = new uint256[](input);
  84. return a[20];
  85. }
  86. function invalid_instruction() public {
  87. assembly {
  88. invalid()
  89. }
  90. }
  91. function byte_cast_failure(uint256 num) public returns (bytes) {
  92. bytes smol_buf = new bytes(num);
  93. //bytes32 b32 = new bytes(num);
  94. bytes32 b32 = bytes32(smol_buf);
  95. return b32;
  96. }
  97. }
  98. @program_id("Crea1hXZv5Snuvs38GW2SJ1vJQ2Z5uBavUnwPwpiaDiQ")
  99. contract child {
  100. constructor() {}
  101. function say_my_name() public pure returns (string memory) {
  102. print("say_my_name");
  103. return "child";
  104. }
  105. }
  106. contract calle_contract {
  107. constructor() {}
  108. function calle_contract_func() public {
  109. revert();
  110. }
  111. }
  112. "#,
  113. );
  114. vm.set_program(0);
  115. vm.constructor(&[]);
  116. let mut _res = vm.function_must_fail(
  117. "math_overflow",
  118. &[BorshToken::Int {
  119. width: 8,
  120. value: BigInt::from(10u8),
  121. }],
  122. );
  123. assert_eq!(
  124. vm.logs,
  125. "runtime_error: math overflow in test.sol:22:20-29,\n"
  126. );
  127. vm.logs.clear();
  128. _res = vm.function_must_fail(
  129. "require_test",
  130. &[BorshToken::Int {
  131. width: 256,
  132. value: BigInt::from(9u8),
  133. }],
  134. );
  135. assert_eq!(
  136. vm.logs,
  137. "runtime_error: sesa require condition failed in test.sol:28:27-33,\n"
  138. );
  139. vm.logs.clear();
  140. _res = vm.function_must_fail("get_storage_bytes", &[]);
  141. assert_eq!(
  142. vm.logs,
  143. "runtime_error: storage array index out of bounds in test.sol:48:19-23,\n"
  144. );
  145. vm.logs.clear();
  146. _res = vm.function_must_fail("set_storage_bytes", &[]);
  147. assert_eq!(
  148. vm.logs,
  149. "runtime_error: storage index out of bounds in test.sol:41:11-12,\n"
  150. );
  151. vm.logs.clear();
  152. _res = vm.function_must_fail(
  153. "read_integer_failure",
  154. &[BorshToken::Uint {
  155. width: 32,
  156. value: BigInt::from(2u8),
  157. }],
  158. );
  159. assert_eq!(
  160. vm.logs,
  161. "runtime_error: read integer out of bounds in test.sol:86:18-30,\n"
  162. );
  163. vm.logs.clear();
  164. _res = vm.function_must_fail(
  165. "trunc_failure",
  166. &[BorshToken::Uint {
  167. width: 256,
  168. value: BigInt::from(u128::MAX),
  169. }],
  170. );
  171. assert_eq!(
  172. vm.logs,
  173. "runtime_error: truncated type overflows in test.sol:91:37-42,\n"
  174. );
  175. vm.logs.clear();
  176. _res = vm.function_must_fail("invalid_instruction", &[]);
  177. assert_eq!(
  178. vm.logs,
  179. "runtime_error: reached invalid instruction in test.sol:102:13-22,\n"
  180. );
  181. vm.logs.clear();
  182. _res = vm.function_must_fail("pop_empty_storage", &[]);
  183. assert_eq!(
  184. vm.logs,
  185. "runtime_error: pop from empty storage array in test.sol:54:9-12,\n"
  186. );
  187. vm.logs.clear();
  188. _res = vm.function_must_fail(
  189. "write_bytes_failure",
  190. &[BorshToken::Uint {
  191. width: 256,
  192. value: BigInt::from(9u8),
  193. }],
  194. );
  195. assert_eq!(
  196. vm.logs,
  197. "runtime_error: data does not fit into buffer in test.sol:81:18-28,\n"
  198. );
  199. vm.logs.clear();
  200. _res = vm.function_must_fail(
  201. "assert_test",
  202. &[BorshToken::Uint {
  203. width: 256,
  204. value: BigInt::from(9u8),
  205. }],
  206. );
  207. println!("{}", vm.logs);
  208. assert_eq!(
  209. vm.logs,
  210. "runtime_error: assert failure in test.sol:34:16-24,\n"
  211. );
  212. vm.logs.clear();
  213. _res = vm.function_must_fail(
  214. "out_of_bounds",
  215. &[BorshToken::Uint {
  216. width: 256,
  217. value: BigInt::from(19u8),
  218. }],
  219. );
  220. assert_eq!(
  221. vm.logs,
  222. "runtime_error: array index out of bounds in test.sol:97:16-21,\n"
  223. );
  224. vm.logs.clear();
  225. _res = vm.function_must_fail(
  226. "write_integer_failure",
  227. &[BorshToken::Uint {
  228. width: 256,
  229. value: BigInt::from(1u8),
  230. }],
  231. );
  232. assert_eq!(
  233. vm.logs,
  234. "runtime_error: integer too large to write in buffer in test.sol:75:18-31,\n"
  235. );
  236. vm.logs.clear();
  237. _res = vm.function_must_fail(
  238. "byte_cast_failure",
  239. &[BorshToken::Uint {
  240. width: 256,
  241. value: BigInt::from(33u8),
  242. }],
  243. );
  244. assert_eq!(
  245. vm.logs,
  246. "runtime_error: bytes cast error in test.sol:110:23-40,\n"
  247. );
  248. vm.logs.clear();
  249. _res = vm.function_must_fail("i_will_revert", &[]);
  250. assert_eq!(
  251. vm.logs,
  252. "runtime_error: revert encountered in test.sol:70:9-15,\n"
  253. );
  254. vm.logs.clear();
  255. _res = vm.function_must_fail("create_child", &[]);
  256. assert_eq!(
  257. vm.logs,
  258. "runtime_error: contract creation failed in test.sol:61:13-36,\n"
  259. );
  260. vm.logs.clear();
  261. }