value.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. // SPDX-License-Identifier: Apache-2.0
  2. use parity_scale_codec::{Decode, Encode};
  3. use crate::build_solidity;
  4. #[test]
  5. fn external_call_value() {
  6. let mut runtime = build_solidity(
  7. r##"
  8. contract b {
  9. a f;
  10. constructor() payable {}
  11. function step1() public {
  12. f = new a();
  13. }
  14. function step2() public {
  15. f.test{value: 1023}(501);
  16. }
  17. }
  18. contract a {
  19. function test(int32 l) public payable {
  20. }
  21. }"##,
  22. );
  23. runtime.set_transferred_value(20000);
  24. runtime.constructor(0, Vec::new());
  25. runtime.set_transferred_value(0);
  26. runtime.function("step1", Vec::new());
  27. runtime.function("step2", Vec::new());
  28. // Transferred value = 1023
  29. assert_eq!(runtime.balance(2), 1023);
  30. let mut runtime = build_solidity(
  31. r##"
  32. contract b {
  33. constructor() payable {}
  34. function step1() public {
  35. a f = new a();
  36. try f.test{value: 1023}(501) {
  37. //
  38. }
  39. catch (bytes) {
  40. //
  41. }
  42. }
  43. }
  44. contract a {
  45. function test(int32 l) public payable {
  46. }
  47. }"##,
  48. );
  49. runtime.set_transferred_value(20000);
  50. runtime.constructor(0, Vec::new());
  51. runtime.set_transferred_value(0);
  52. runtime.function("step1", Vec::new());
  53. // Transferred value = 1023
  54. assert_eq!(runtime.balance(2), 1023);
  55. }
  56. #[test]
  57. fn constructor_value() {
  58. let mut runtime = build_solidity(
  59. r##"
  60. contract b {
  61. constructor() payable {}
  62. function step1() public {
  63. a f = new a{value: 500}();
  64. }
  65. }
  66. contract a {
  67. constructor() payable {}
  68. function test(int32 l) public payable {
  69. }
  70. }"##,
  71. );
  72. runtime.set_transferred_value(20000);
  73. runtime.constructor(0, Vec::new());
  74. runtime.set_transferred_value(0);
  75. runtime.function("step1", Vec::new());
  76. assert_eq!(runtime.balance(2), 500);
  77. let mut runtime = build_solidity(
  78. r##"
  79. contract b {
  80. constructor() payable {}
  81. function step1() public {
  82. a f = (new a){value: 0}();
  83. }
  84. }
  85. contract a {
  86. function test(int32 l) public payable {
  87. }
  88. }"##,
  89. );
  90. runtime.set_transferred_value(20000);
  91. runtime.constructor(0, Vec::new());
  92. runtime.set_transferred_value(0);
  93. runtime.function("step1", Vec::new());
  94. assert_eq!(runtime.balance(2), 0);
  95. let mut runtime = build_solidity(
  96. r##"
  97. contract b {
  98. constructor() payable {}
  99. function step1() public {
  100. a f = new a{value: 499}();
  101. }
  102. }
  103. contract a {
  104. constructor() payable {}
  105. function test(int32 l) public payable {
  106. }
  107. }"##,
  108. );
  109. runtime.set_transferred_value(20000);
  110. runtime.constructor(0, Vec::new());
  111. runtime.set_transferred_value(0);
  112. runtime.function("step1", Vec::new());
  113. assert_eq!(runtime.balance(2), 499);
  114. let mut runtime = build_solidity(
  115. r##"
  116. contract b {
  117. constructor() payable {}
  118. function step1() public {
  119. try (new a{value: 511})() {
  120. //
  121. }
  122. catch (bytes) {
  123. //
  124. }
  125. }
  126. }
  127. contract a {
  128. constructor() payable {}
  129. function test(int32 l) public payable {
  130. }
  131. }"##,
  132. );
  133. runtime.set_transferred_value(20000);
  134. runtime.constructor(0, Vec::new());
  135. runtime.set_transferred_value(0);
  136. runtime.function("step1", Vec::new());
  137. assert_eq!(runtime.balance(2), 511);
  138. let mut runtime = build_solidity(
  139. r##"
  140. contract b {
  141. constructor() payable {}
  142. function step1() public {
  143. try (new a){value: 511}() returns (a) {
  144. //
  145. }
  146. catch (bytes) {
  147. //
  148. }
  149. }
  150. }
  151. contract a {
  152. constructor() payable {}
  153. function test(int32 l) public payable {
  154. }
  155. }"##,
  156. );
  157. runtime.set_transferred_value(20000);
  158. runtime.constructor(0, Vec::new());
  159. runtime.set_transferred_value(0);
  160. runtime.function("step1", Vec::new());
  161. assert_eq!(runtime.balance(2), 511)
  162. }
  163. #[test]
  164. fn constructor_salt() {
  165. let mut runtime = build_solidity(
  166. r##"
  167. contract b {
  168. function step1() public {
  169. a f = new a{salt: 0}();
  170. }
  171. }
  172. contract a {
  173. function test(int32 l) public payable {
  174. }
  175. }"##,
  176. );
  177. runtime.constructor(0, Vec::new());
  178. runtime.function("step1", Vec::new());
  179. let mut runtime = build_solidity(
  180. r#"
  181. contract b {
  182. function step1() public {
  183. a f = new a{salt: hex"01"}();
  184. }
  185. }
  186. contract a {
  187. function test(int32 l) public payable {
  188. }
  189. }"#,
  190. );
  191. runtime.constructor(0, Vec::new());
  192. runtime.function("step1", Vec::new());
  193. // we can instantiate the same contract if we provide a different contract
  194. let mut runtime = build_solidity(
  195. r#"
  196. contract b {
  197. function step1() public {
  198. a f = new a{salt: hex"01"}();
  199. f = new a{salt: hex"02"}();
  200. }
  201. }
  202. contract a {
  203. function test(int32 l) public payable {
  204. }
  205. }"#,
  206. );
  207. runtime.constructor(0, Vec::new());
  208. runtime.function("step1", Vec::new());
  209. }
  210. #[test]
  211. fn this_address() {
  212. let mut runtime = build_solidity(
  213. r##"
  214. contract b {
  215. function step1() public returns (address) {
  216. return address(this);
  217. }
  218. }"##,
  219. );
  220. runtime.constructor(0, Vec::new());
  221. runtime.function("step1", Vec::new());
  222. assert_eq!(runtime.output(), runtime.caller());
  223. let mut runtime = build_solidity(
  224. r##"
  225. contract b {
  226. function step1() public returns (b) {
  227. return this;
  228. }
  229. }"##,
  230. );
  231. runtime.constructor(0, Vec::new());
  232. runtime.function("step1", Vec::new());
  233. assert_eq!(runtime.output(), runtime.caller());
  234. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  235. struct Ret(u32);
  236. let mut runtime = build_solidity(
  237. r##"
  238. contract b {
  239. int32 s;
  240. function step1() public returns (int32) {
  241. this.other{flags: 8}(102);
  242. return s;
  243. }
  244. function other(int32 n) public {
  245. s = n;
  246. }
  247. }"##,
  248. );
  249. runtime.constructor(0, Vec::new());
  250. runtime.function("step1", Vec::new());
  251. assert_eq!(runtime.output(), Ret(102).encode());
  252. let mut runtime = build_solidity(
  253. r##"
  254. contract b {
  255. function step1() public returns (b) {
  256. return this;
  257. }
  258. }"##,
  259. );
  260. runtime.constructor(0, Vec::new());
  261. runtime.function("step1", Vec::new());
  262. assert_eq!(runtime.output(), runtime.caller());
  263. }
  264. #[test]
  265. fn balance() {
  266. let mut runtime = build_solidity(
  267. r##"
  268. contract b {
  269. other o;
  270. constructor() public payable {
  271. o = new other();
  272. }
  273. function step1() public returns (uint128) {
  274. return address(this).balance;
  275. }
  276. function step2() public returns (uint128) {
  277. return o.balance();
  278. }
  279. }
  280. contract other {
  281. function balance() public returns (uint128) {
  282. return address(this).balance;
  283. }
  284. }"##,
  285. );
  286. runtime.set_transferred_value(20000);
  287. runtime.constructor(0, Vec::new());
  288. runtime.set_transferred_value(0);
  289. runtime.function("step1", Vec::new());
  290. // Constructor received 20000, 0 were sent to "o"
  291. assert_eq!(runtime.output(), 20000u128.to_le_bytes());
  292. runtime.function("step2", Vec::new());
  293. assert_eq!(runtime.output(), 0u128.to_le_bytes());
  294. }
  295. #[test]
  296. fn selfdestruct() {
  297. let mut runtime = build_solidity(
  298. r##"
  299. contract c {
  300. other o;
  301. constructor() payable {}
  302. function step1() public {
  303. o = new other{value: 511}();
  304. }
  305. function step2() public {
  306. o.goaway(payable(address(this)));
  307. }
  308. }
  309. contract other {
  310. constructor() payable {}
  311. function goaway(address payable recipient) public returns (bool) {
  312. selfdestruct(recipient);
  313. }
  314. }"##,
  315. );
  316. runtime.set_transferred_value(20000);
  317. runtime.constructor(0, Vec::new());
  318. runtime.set_transferred_value(0);
  319. runtime.function("step1", Vec::new());
  320. assert_eq!(runtime.balance(0), 20000 - 511);
  321. runtime.function("step2", Vec::new());
  322. assert_eq!(runtime.balance(0), 20000);
  323. }
  324. #[test]
  325. fn send_and_transfer() {
  326. let mut runtime = build_solidity(
  327. r##"
  328. contract c {
  329. other o;
  330. constructor() public payable {
  331. o = new other();
  332. }
  333. function step1() public returns (bool) {
  334. return payable(o).send(511);
  335. }
  336. }
  337. contract other {
  338. function giveme() public payable {
  339. }
  340. }"##,
  341. );
  342. runtime.set_transferred_value(20000);
  343. runtime.constructor(0, Vec::new());
  344. runtime.function("step1", Vec::new());
  345. // no receive() required for send/transfer
  346. assert_eq!(runtime.output(), true.encode());
  347. assert_eq!(runtime.balance(2), 511);
  348. let mut runtime = build_solidity(
  349. r##"
  350. contract c {
  351. other o;
  352. constructor() public payable {
  353. o = new other();
  354. }
  355. function step1() public returns (bool) {
  356. return payable(o).send(511);
  357. }
  358. }
  359. contract other {
  360. receive() external payable {
  361. }
  362. }"##,
  363. );
  364. runtime.set_transferred_value(20000);
  365. runtime.constructor(0, Vec::new());
  366. runtime.set_transferred_value(0);
  367. runtime.function("step1", Vec::new());
  368. assert_eq!(runtime.output(), true.encode());
  369. assert_eq!(runtime.balance(2), 511);
  370. let mut runtime = build_solidity(
  371. r##"
  372. contract c {
  373. other o;
  374. constructor() public payable {
  375. o = new other();
  376. }
  377. function step1() public {
  378. payable(o).transfer(511);
  379. }
  380. }
  381. contract other {
  382. function giveme() public {
  383. }
  384. }"##,
  385. );
  386. runtime.set_transferred_value(20000);
  387. runtime.constructor(0, Vec::new());
  388. runtime.set_transferred_value(0);
  389. runtime.function("step1", Vec::new());
  390. assert_eq!(runtime.balance(2), 511);
  391. let mut runtime = build_solidity(
  392. r##"
  393. contract c {
  394. other o;
  395. constructor() public payable {
  396. o = new other();
  397. }
  398. function step1() public {
  399. payable(o).transfer(511);
  400. }
  401. }
  402. contract other {
  403. receive() external payable {
  404. }
  405. }"##,
  406. );
  407. runtime.set_transferred_value(20000);
  408. runtime.constructor(0, Vec::new());
  409. runtime.set_transferred_value(0);
  410. runtime.function("step1", Vec::new());
  411. assert_eq!(runtime.balance(2), 511);
  412. }
  413. #[test]
  414. fn nonpayable_constructor_reverts() {
  415. let mut runtime = build_solidity(
  416. r#"contract C {
  417. uint8 public c;
  418. constructor (uint8 val) {
  419. c = val;
  420. }
  421. }"#,
  422. );
  423. let mut input = runtime.blobs()[0].constructors[0].to_vec();
  424. let storage_value = 123;
  425. input.push(storage_value);
  426. // Expect the deploy to fail with value
  427. runtime.set_transferred_value(1);
  428. runtime.raw_constructor_failure(input.clone());
  429. // The same input should work without value
  430. runtime.set_transferred_value(0);
  431. runtime.raw_constructor(input.clone());
  432. runtime.function("c", Vec::new());
  433. assert_eq!(runtime.output(), storage_value.encode());
  434. }
  435. #[test]
  436. fn transfer_bubble_up() {
  437. let mut runtime = build_solidity(
  438. r##"
  439. contract C {
  440. function c(uint128 amount) public payable {
  441. Other o = new Other{value: 1000}();
  442. o.payback(amount);
  443. }
  444. }
  445. contract Other {
  446. constructor() payable {}
  447. function payback(uint128 amount) public payable {
  448. payable(msg.sender).transfer(amount);
  449. }
  450. }"##,
  451. );
  452. runtime.set_transferred_value(2000);
  453. runtime.function("c", 100u128.encode());
  454. runtime.function_expect_failure("c", 1000000u128.encode());
  455. assert!(runtime.output().is_empty());
  456. }
  457. #[test]
  458. fn send_does_not_bubble_up() {
  459. let mut runtime = build_solidity(
  460. r##"
  461. contract C {
  462. function c(uint128 amount) public payable returns(bool) {
  463. Other o = new Other{value: 1000}();
  464. return o.payback(amount);
  465. }
  466. }
  467. contract Other {
  468. constructor() payable {}
  469. function payback(uint128 amount) public payable returns(bool) {
  470. return payable(msg.sender).send(amount);
  471. }
  472. }"##,
  473. );
  474. runtime.set_transferred_value(2000);
  475. runtime.function("c", 100u128.encode());
  476. assert_eq!(runtime.output(), true.encode());
  477. runtime.function("c", 1000000u128.encode());
  478. assert_eq!(runtime.output(), false.encode());
  479. }