yul.rs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. // SPDX-License-Identifier: Apache-2.0
  2. use crate::build_solidity;
  3. use parity_scale_codec::{Decode, Encode};
  4. use primitive_types::U256;
  5. #[derive(Debug, Encode, Decode)]
  6. struct Val256(U256);
  7. #[test]
  8. fn assign_suffixes() {
  9. #[derive(Debug, Encode, Decode)]
  10. struct CallDataInput {
  11. pub input: U256,
  12. pub vec: Vec<u32>,
  13. }
  14. let mut runtime = build_solidity(
  15. r#"
  16. contract testing {
  17. struct stru_test {
  18. string a;
  19. uint b;
  20. }
  21. stru_test t_s_t;
  22. function test_local_vec(uint256 input) public pure returns (uint256 ret) {
  23. uint256[] vec;
  24. vec.push(uint256(4));
  25. assembly {
  26. vec := add(input, 7)
  27. input := 6
  28. ret := vec
  29. }
  30. }
  31. function test_struct(uint256 input) public pure returns (uint256 ret) {
  32. stru_test tt = stru_test({a: "tea", b: 5});
  33. assembly {
  34. tt := add(input, 7)
  35. input := 6
  36. ret := tt
  37. }
  38. }
  39. function test_mem_vec(uint256 input) public pure returns (uint256 ret) {
  40. uint256[] memory vec;
  41. vec.push(uint256(4));
  42. assembly {
  43. vec := add(input, 7)
  44. input := 9
  45. ret := vec
  46. }
  47. }
  48. function test_mem_struct(uint256 input) public pure returns (uint256 ret) {
  49. stru_test memory tt = stru_test({a: "tea", b: 5});
  50. assembly {
  51. tt := add(input, 7)
  52. input := 9
  53. ret := tt
  54. }
  55. }
  56. function calldata_vec(uint256 input, uint32[] calldata vec) public view returns (uint256 ret) {
  57. assembly {
  58. vec.offset := add(input, 7)
  59. input := 9
  60. ret := vec.offset
  61. }
  62. }
  63. function storage_struct(uint256 input) public returns (uint256 ret) {
  64. stru_test storage local_t = t_s_t;
  65. assembly {
  66. local_t.slot := add(input, 7)
  67. input := 90
  68. ret := local_t.slot
  69. }
  70. }
  71. }
  72. "#,
  73. );
  74. runtime.function("test_local_vec", Val256(U256::from(7)).encode());
  75. assert_eq!(runtime.output(), Val256(U256::from(14)).encode());
  76. runtime.function("test_struct", Val256(U256::from(20)).encode());
  77. assert_eq!(runtime.output(), Val256(U256::from(27)).encode());
  78. runtime.function("test_mem_vec", Val256(U256::from(30)).encode());
  79. assert_eq!(runtime.output(), Val256(U256::from(37)).encode());
  80. runtime.function("test_mem_struct", Val256(U256::from(8)).encode());
  81. assert_eq!(runtime.output(), Val256(U256::from(15)).encode());
  82. runtime.function(
  83. "calldata_vec",
  84. CallDataInput {
  85. input: U256::from(19),
  86. vec: vec![0, 1, 2, 3, 4],
  87. }
  88. .encode(),
  89. );
  90. assert_eq!(runtime.output(), Val256(U256::from(26)).encode());
  91. runtime.function("storage_struct", Val256(U256::from(17)).encode());
  92. assert_eq!(runtime.output(), Val256(U256::from(24)).encode());
  93. }
  94. #[test]
  95. fn eth_builtins() {
  96. let mut runtime = build_solidity(
  97. r#"
  98. contract testing {
  99. function test_address() public view returns (uint256 ret) {
  100. assembly {
  101. let a := address()
  102. ret := a
  103. }
  104. }
  105. function test_balance() public view returns (uint256 ret) {
  106. assembly {
  107. let a := address()
  108. ret := balance(a)
  109. }
  110. }
  111. function test_selfbalance() public view returns (uint256 ret) {
  112. assembly {
  113. let a := selfbalance()
  114. ret := a
  115. }
  116. }
  117. function test_caller() public view returns (uint256 ret) {
  118. assembly {
  119. let a := caller()
  120. ret := a
  121. }
  122. }
  123. function test_callvalue() public payable returns (uint256 ret) {
  124. assembly {
  125. let a := callvalue()
  126. ret := a
  127. }
  128. }
  129. }"#,
  130. );
  131. runtime.constructor(0, Vec::new());
  132. runtime.function("test_address", Vec::new());
  133. let mut b_vec = runtime.output().to_vec();
  134. b_vec.reverse();
  135. assert_eq!(b_vec, runtime.caller().to_vec());
  136. runtime.function("test_balance", Vec::new());
  137. assert_eq!(runtime.output()[..16].to_vec(), runtime.balance(0).encode());
  138. runtime.function("test_selfbalance", Vec::new());
  139. assert_eq!(runtime.output()[..16].to_vec(), runtime.balance(0).encode());
  140. runtime.function("test_caller", Vec::new());
  141. let mut b_vec = runtime.output().to_vec();
  142. b_vec.reverse();
  143. assert_eq!(b_vec, runtime.caller().to_vec());
  144. runtime.set_transferred_value(0xdeadcafe);
  145. runtime.raw_function(runtime.selector(0, "test_callvalue").to_vec());
  146. let mut expected = 0xdeadcafeu32.to_le_bytes().to_vec();
  147. expected.resize(32, 0);
  148. assert_eq!(runtime.output(), expected);
  149. }
  150. #[test]
  151. fn switch_statement() {
  152. let mut runtime = build_solidity(
  153. r#"
  154. contract Testing {
  155. function switch_default(uint a) public pure returns (uint b) {
  156. b = 4;
  157. assembly {
  158. switch a
  159. case 1 {
  160. b := 5
  161. }
  162. case 2 {
  163. b := 6
  164. }
  165. default {
  166. b := 7
  167. }
  168. }
  169. if (b == 7) {
  170. b += 2;
  171. }
  172. }
  173. function switch_no_default(uint a) public pure returns (uint b) {
  174. b = 4;
  175. assembly {
  176. switch a
  177. case 1 {
  178. b := 5
  179. }
  180. case 2 {
  181. b := 6
  182. }
  183. }
  184. if (b == 5) {
  185. b -= 2;
  186. }
  187. }
  188. function switch_no_case(uint a) public pure returns (uint b) {
  189. b = 7;
  190. assembly {
  191. switch a
  192. default {
  193. b := 5
  194. }
  195. }
  196. if (b == 5) {
  197. b -= 1;
  198. }
  199. }
  200. }
  201. "#,
  202. );
  203. runtime.constructor(0, Vec::new());
  204. runtime.function("switch_default", Val256(U256::from(1)).encode());
  205. assert_eq!(runtime.output(), Val256(U256::from(5)).encode());
  206. runtime.function("switch_default", Val256(U256::from(2)).encode());
  207. assert_eq!(runtime.output(), Val256(U256::from(6)).encode());
  208. runtime.function("switch_default", Val256(U256::from(6)).encode());
  209. assert_eq!(runtime.output(), Val256(U256::from(9)).encode());
  210. runtime.function("switch_no_default", Val256(U256::from(1)).encode());
  211. assert_eq!(runtime.output(), Val256(U256::from(3)).encode());
  212. runtime.function("switch_no_default", Val256(U256::from(2)).encode());
  213. assert_eq!(runtime.output(), Val256(U256::from(6)).encode());
  214. runtime.function("switch_no_default", Val256(U256::from(6)).encode());
  215. assert_eq!(runtime.output(), Val256(U256::from(4)).encode());
  216. runtime.function("switch_no_case", Val256(U256::from(3)).encode());
  217. assert_eq!(runtime.output(), Val256(U256::from(4)).encode());
  218. }