libraries.rs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // SPDX-License-Identifier: Apache-2.0
  2. use crate::build_solidity;
  3. use parity_scale_codec::{Decode, Encode};
  4. #[test]
  5. fn simple() {
  6. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  7. struct Val(u64);
  8. let mut runtime = build_solidity(
  9. r##"
  10. contract test {
  11. function foo(uint64 x) public pure returns (uint64) {
  12. return ints.max(x, 65536);
  13. }
  14. function bar() public pure returns (uint64) {
  15. return ints.bar();
  16. }
  17. }
  18. library ints {
  19. uint64 constant CONSTANT_BAR = 102;
  20. function max(uint64 a, uint64 b) internal pure returns (uint64) {
  21. return a > b ? a : b;
  22. }
  23. function bar() internal pure returns (uint64) {
  24. return CONSTANT_BAR;
  25. }
  26. }"##,
  27. );
  28. runtime.constructor(0, Vec::new());
  29. runtime.function("foo", Val(102).encode());
  30. assert_eq!(runtime.vm.output, Val(65536).encode());
  31. runtime.function("bar", Vec::new());
  32. assert_eq!(runtime.vm.output, Val(102).encode());
  33. }
  34. #[test]
  35. fn using() {
  36. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  37. struct Val(u64);
  38. let mut runtime = build_solidity(
  39. r##"
  40. contract test {
  41. using ints for uint64;
  42. function foo(uint64 x) public pure returns (uint64) {
  43. return x.max(65536);
  44. }
  45. }
  46. library ints {
  47. function max(uint64 a, uint64 b) internal pure returns (uint64) {
  48. return a > b ? a : b;
  49. }
  50. }"##,
  51. );
  52. runtime.constructor(0, Vec::new());
  53. runtime.function("foo", Val(102).encode());
  54. assert_eq!(runtime.vm.output, Val(65536).encode());
  55. // the using directive can specify a different type than the function in the library,
  56. // as long as it casts implicitly and matches the type of method call _exactly_
  57. let mut runtime = build_solidity(
  58. r##"
  59. contract test {
  60. using ints for uint32;
  61. function foo(uint32 x) public pure returns (uint64) {
  62. // x is 32 bit but the max function takes 64 bit uint
  63. return x.max(65536);
  64. }
  65. }
  66. library ints {
  67. function max(uint64 a, uint64 b) internal pure returns (uint64) {
  68. return a > b ? a : b;
  69. }
  70. }"##,
  71. );
  72. runtime.constructor(0, Vec::new());
  73. runtime.function("foo", 102u32.encode());
  74. assert_eq!(runtime.vm.output, Val(65536).encode());
  75. let mut runtime = build_solidity(
  76. r##"
  77. contract test {
  78. using lib for int32[100];
  79. bool i_exists_to_make_bar_have_non_zero_storage_slot;
  80. int32[100] bar;
  81. function foo() public returns (int64) {
  82. bar.set(10, 571);
  83. return bar[10];
  84. }
  85. }
  86. library lib {
  87. function set(int32[100] storage a, uint index, int32 val) internal {
  88. a[index] = val;
  89. }
  90. }"##,
  91. );
  92. runtime.constructor(0, Vec::new());
  93. runtime.function("foo", Vec::new());
  94. assert_eq!(runtime.vm.output, Val(571).encode());
  95. }
  96. #[test]
  97. fn using_in_base() {
  98. let mut runtime = build_solidity(
  99. r#"
  100. contract r is base {
  101. function baz(uint64 arg) public returns (bool) {
  102. bar(arg);
  103. return x;
  104. }
  105. }
  106. library Lib {
  107. function foo(uint64 a, uint64 b) internal returns (bool) {
  108. return a == b;
  109. }
  110. }
  111. abstract contract base {
  112. using Lib for *;
  113. bool x;
  114. function bar(uint64 arg) internal {
  115. x = arg.foo(102);
  116. }
  117. }
  118. "#,
  119. );
  120. runtime.constructor(0, Vec::new());
  121. runtime.function("baz", 102u64.encode());
  122. assert_eq!(runtime.vm.output, true.encode());
  123. }