modifier.rs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. // SPDX-License-Identifier: Apache-2.0
  2. use crate::build_solidity;
  3. use parity_scale_codec::{Decode, Encode};
  4. #[test]
  5. fn chain() {
  6. let mut runtime = build_solidity(
  7. r#"
  8. contract c {
  9. uint16 public var;
  10. modifier foo() {
  11. bool boom = true;
  12. if (boom) {
  13. _;
  14. }
  15. }
  16. function bar() foo() public {
  17. var = 7;
  18. }
  19. }"#,
  20. );
  21. runtime.constructor(0, Vec::new());
  22. let slot = [0u8; 32];
  23. assert_eq!(runtime.storage().get(&slot), None);
  24. runtime.function("bar", Vec::new());
  25. assert_eq!(runtime.storage().get(&slot).unwrap(), &vec!(7, 0));
  26. let mut runtime = build_solidity(
  27. r##"
  28. contract c {
  29. uint16 public var;
  30. modifier mod1 {
  31. var = 3;
  32. _;
  33. var = 5;
  34. }
  35. function test() mod1 public {
  36. assert(var == 3);
  37. var = 7;
  38. }
  39. }"##,
  40. );
  41. runtime.constructor(0, Vec::new());
  42. let slot = [0u8; 32];
  43. assert_eq!(runtime.storage().get(&slot), None);
  44. runtime.function("test", Vec::new());
  45. assert_eq!(runtime.storage().get(&slot).unwrap(), &vec!(5, 0));
  46. // now test modifier with argument and test that function argument is passed on
  47. let mut runtime = build_solidity(
  48. r##"
  49. contract c {
  50. uint16 public var;
  51. modifier mod1(uint16 v) {
  52. var = 3;
  53. _;
  54. assert(var == 11);
  55. var = v;
  56. }
  57. function test(uint16 x) mod1(x - 6) public {
  58. assert(var == 3);
  59. var = x;
  60. }
  61. }"##,
  62. );
  63. runtime.constructor(0, Vec::new());
  64. let slot = [0u8; 32];
  65. assert_eq!(runtime.storage().get(&slot), None);
  66. runtime.function("test", 11u16.encode());
  67. assert_eq!(runtime.storage().get(&slot).unwrap(), &vec!(5, 0));
  68. // now test modifier with argument and test that function argument is passed on
  69. let mut runtime = build_solidity(
  70. r##"
  71. contract c {
  72. uint16 public var;
  73. modifier mod1(uint16 v) {
  74. assert(var == 0);
  75. var = 3;
  76. _;
  77. assert(var == 17);
  78. var = v;
  79. }
  80. modifier mod2(uint16 v) {
  81. assert(var == 3);
  82. var = 9;
  83. _;
  84. assert(var == 11);
  85. var = v;
  86. }
  87. function test(uint16 x) mod1(x - 6) mod2(x + 6) public {
  88. assert(var == 9);
  89. var = x;
  90. }
  91. }"##,
  92. );
  93. runtime.constructor(0, Vec::new());
  94. let slot = [0u8; 32];
  95. assert_eq!(runtime.storage().get(&slot), None);
  96. runtime.function("test", 11u16.encode());
  97. assert_eq!(runtime.storage().get(&slot).unwrap(), &vec!(5, 0));
  98. // two placeholders means the following function is called twice.
  99. let mut runtime = build_solidity(
  100. r##"
  101. contract c {
  102. uint16 public var;
  103. modifier m {
  104. _;
  105. _;
  106. }
  107. function test() m public {
  108. var += 3;
  109. }
  110. }"##,
  111. );
  112. runtime.constructor(0, Vec::new());
  113. let slot = [0u8; 32];
  114. assert_eq!(runtime.storage().get(&slot), None);
  115. runtime.function("test", Vec::new());
  116. assert_eq!(runtime.storage().get(&slot).unwrap(), &vec!(6, 0));
  117. }
  118. #[test]
  119. fn inherit_modifier() {
  120. let mut runtime = build_solidity(
  121. r##"
  122. contract c is base {
  123. function test() md2 public {
  124. assert(s2 == 2);
  125. s2 += 3;
  126. }
  127. }
  128. abstract contract base {
  129. bool private s1;
  130. int32 internal s2;
  131. modifier md2 {
  132. s2 += 2;
  133. _;
  134. s2 += 2;
  135. }
  136. }"##,
  137. );
  138. runtime.constructor(0, Vec::new());
  139. let mut slot = [0u8; 32];
  140. slot[0] = 1;
  141. assert_eq!(runtime.storage().get(&slot), None);
  142. runtime.function("test", Vec::new());
  143. assert_eq!(runtime.storage().get(&slot).unwrap(), &vec!(7, 0, 0, 0));
  144. // now override it
  145. let mut runtime = build_solidity(
  146. r##"
  147. contract c is base {
  148. function test() md2 public {
  149. assert(s2 == 2);
  150. s2 += 3;
  151. }
  152. modifier md2 override {
  153. s2 += 2;
  154. _;
  155. s2 += 5;
  156. }
  157. }
  158. abstract contract base {
  159. bool private s1;
  160. int32 internal s2;
  161. modifier md2 virtual {
  162. s2 += 1;
  163. _;
  164. s2 += 1;
  165. }
  166. }"##,
  167. );
  168. runtime.constructor(0, Vec::new());
  169. let mut slot = [0u8; 32];
  170. slot[0] = 1;
  171. assert_eq!(runtime.storage().get(&slot), None);
  172. runtime.function("test", Vec::new());
  173. assert_eq!(runtime.storage().get(&slot).unwrap(), &vec!(10, 0, 0, 0));
  174. }
  175. #[test]
  176. fn return_values() {
  177. // in the modifier syntax, there are no return values
  178. // however, the generated cfg has the same arguments/returns the function is on attached
  179. // return simple value
  180. let mut runtime = build_solidity(
  181. r##"
  182. contract c {
  183. int64 s2;
  184. function test() md2 public returns (int64) {
  185. assert(s2 == 2);
  186. s2 += 3;
  187. return s2;
  188. }
  189. modifier md2 {
  190. s2 += 2;
  191. _;
  192. s2 += 2;
  193. }
  194. }"##,
  195. );
  196. runtime.constructor(0, Vec::new());
  197. runtime.function("test", Vec::new());
  198. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  199. struct Val(u64);
  200. assert_eq!(runtime.output(), Val(5).encode());
  201. let mut runtime = build_solidity(
  202. r##"
  203. struct S {
  204. int64 f1;
  205. string f2;
  206. }
  207. contract c {
  208. int64 s2;
  209. function test() md2 public returns (bool, S) {
  210. assert(s2 == 2);
  211. s2 += 3;
  212. return (true, S({ f1: s2, f2: "Hello, World!" }));
  213. }
  214. modifier md2 {
  215. s2 += 2;
  216. _;
  217. s2 += 2;
  218. }
  219. }"##,
  220. );
  221. runtime.constructor(0, Vec::new());
  222. runtime.function("test", Vec::new());
  223. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  224. struct StructS(bool, u64, String);
  225. assert_eq!(
  226. runtime.output(),
  227. StructS(true, 5, String::from("Hello, World!")).encode()
  228. );
  229. }
  230. #[test]
  231. fn repeated_modifier() {
  232. let mut runtime = build_solidity(
  233. r##"
  234. contract Test {
  235. modifier notZero(uint64 num) {
  236. require(num != 0, "invalid number");
  237. _;
  238. }
  239. function contfunc(uint64 num1, uint64 num2) public notZero(num1) notZero(num2) {
  240. // any code
  241. }
  242. }"##,
  243. );
  244. runtime.constructor(0, Vec::new());
  245. runtime.function_expect_failure("contfunc", (1u64, 0u64).encode());
  246. runtime.function_expect_failure("contfunc", (0u64, 0u64).encode());
  247. runtime.function_expect_failure("contfunc", (0u64, 1u64).encode());
  248. runtime.function("contfunc", (1u64, 1u64).encode());
  249. }
  250. #[test]
  251. fn modifier_in_library() {
  252. let mut runtime = build_solidity(
  253. r##"
  254. library LibWidthMod {
  255. modifier m(uint64 v) {
  256. require(v > 100);
  257. _;
  258. }
  259. function withMod(uint64 self) m(self) internal view {
  260. require(self > 10);
  261. }
  262. }
  263. contract Test {
  264. using LibWidthMod for uint64;
  265. function test(uint64 n) external {
  266. n.withMod();
  267. LibWidthMod.withMod(n);
  268. }
  269. }"##,
  270. );
  271. runtime.constructor(0, Vec::new());
  272. runtime.function_expect_failure("test", 0u64.encode());
  273. runtime.function_expect_failure("test", 50u64.encode());
  274. runtime.function_expect_failure("test", 100u64.encode());
  275. runtime.function("test", 200u64.encode());
  276. }