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