events.rs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. // SPDX-License-Identifier: Apache-2.0
  2. use crate::build_solidity;
  3. use ink_env::hash::{Blake2x256, CryptoHash};
  4. use ink_primitives::{AccountId, Hash};
  5. use parity_scale_codec::Encode;
  6. use solang::{file_resolver::FileResolver, Target};
  7. use std::ffi::OsStr;
  8. fn topic_hash(encoded: &[u8]) -> Hash {
  9. let mut buf = [0; 32];
  10. if encoded.len() <= 32 {
  11. buf[..encoded.len()].copy_from_slice(encoded);
  12. } else {
  13. <Blake2x256 as CryptoHash>::hash(encoded, &mut buf);
  14. };
  15. buf.into()
  16. }
  17. fn event_topic(signature: &str) -> Hash {
  18. let mut buf = [0; 32];
  19. <Blake2x256 as CryptoHash>::hash(signature.as_bytes(), &mut buf);
  20. buf.into()
  21. }
  22. #[test]
  23. fn anonymous() {
  24. let mut runtime = build_solidity(
  25. r##"
  26. contract a {
  27. event foo(bool b) anonymous;
  28. function emit_event() public {
  29. emit foo(true);
  30. }
  31. }"##,
  32. );
  33. runtime.constructor(0, Vec::new());
  34. runtime.function("emit_event", Vec::new());
  35. assert_eq!(runtime.events().len(), 1);
  36. let event = &runtime.events()[0];
  37. assert_eq!(event.topics.len(), 0);
  38. assert_eq!(event.data, true.encode());
  39. }
  40. #[test]
  41. fn emit() {
  42. #[derive(Encode)]
  43. struct Foo(bool, u32, i64);
  44. #[derive(Encode)]
  45. struct Bar(u32, u64, String);
  46. let mut runtime = build_solidity(
  47. r#"
  48. contract a {
  49. event foo(bool,uint32,int64 indexed i);
  50. event bar(uint32,uint64,string indexed s);
  51. function emit_event() public {
  52. emit foo(true, 102, 1);
  53. emit bar(0xdeadcafe, 102, "foobar");
  54. }
  55. }"#,
  56. );
  57. runtime.constructor(0, Vec::new());
  58. runtime.function("emit_event", Vec::new());
  59. assert_eq!(runtime.events().len(), 2);
  60. let event = &runtime.events()[0];
  61. assert_eq!(event.topics.len(), 2);
  62. assert_eq!(event.topics[0], event_topic("foo(bool,uint32,int64)"));
  63. assert_eq!(event.topics[1], topic_hash(&1i64.encode()[..]));
  64. assert_eq!(event.data, Foo(true, 102, 1).encode());
  65. let event = &runtime.events()[1];
  66. assert_eq!(event.topics.len(), 2);
  67. println!("topic hash: {:?}", event.topics[0]);
  68. println!("topic hash: {:?}", event.topics[0]);
  69. assert_eq!(event.topics[0], event_topic("bar(uint32,uint64,string)"));
  70. assert_eq!(
  71. event.topics[1],
  72. topic_hash(&"foobar".to_string().encode()[..])
  73. );
  74. assert_eq!(event.data, Bar(0xdeadcafe, 102, "foobar".into()).encode());
  75. }
  76. #[test]
  77. fn event_imported() {
  78. let mut cache = FileResolver::default();
  79. cache.set_file_contents(
  80. "a.sol",
  81. r#"
  82. import "b.sol";
  83. contract foo {
  84. function emit_event() public {
  85. emit bar(102, true);
  86. }
  87. }
  88. "#
  89. .to_string(),
  90. );
  91. cache.set_file_contents(
  92. "b.sol",
  93. r#"
  94. event bar (uint32 indexed f1, bool x);
  95. "#
  96. .to_string(),
  97. );
  98. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  99. assert!(!ns.diagnostics.any_errors());
  100. let mut cache = FileResolver::default();
  101. cache.set_file_contents(
  102. "a.sol",
  103. r#"
  104. import "b.sol";
  105. contract foo {
  106. function emit_event() public {
  107. emit baz.bar(102, true);
  108. }
  109. }
  110. "#
  111. .to_string(),
  112. );
  113. cache.set_file_contents(
  114. "b.sol",
  115. r#"
  116. abstract contract baz {
  117. event bar (uint32 indexed f1, bool x);
  118. }
  119. "#
  120. .to_string(),
  121. );
  122. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  123. assert!(!ns.diagnostics.any_errors());
  124. let mut cache = FileResolver::default();
  125. cache.set_file_contents(
  126. "a.sol",
  127. r#"
  128. import "b.sol" as X;
  129. contract foo {
  130. function emit_event() public {
  131. emit X.baz.bar(102, true);
  132. }
  133. }
  134. "#
  135. .to_string(),
  136. );
  137. cache.set_file_contents(
  138. "b.sol",
  139. r#"
  140. abstract contract baz {
  141. event bar (uint32 indexed f1, bool x);
  142. }
  143. "#
  144. .to_string(),
  145. );
  146. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  147. assert!(!ns.diagnostics.any_errors());
  148. let mut cache = FileResolver::default();
  149. cache.set_file_contents(
  150. "a.sol",
  151. r#"
  152. import "b.sol" as X;
  153. contract foo {
  154. function emit_event() public {
  155. emit X.bar(102, true);
  156. }
  157. }
  158. "#
  159. .to_string(),
  160. );
  161. cache.set_file_contents(
  162. "b.sol",
  163. r#"
  164. event bar (uint32 indexed f1, bool x);
  165. "#
  166. .to_string(),
  167. );
  168. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  169. assert!(!ns.diagnostics.any_errors());
  170. }
  171. /// FIXME: Use the exact same event structure once the `Option<T>` type is available
  172. #[test]
  173. fn erc20_ink_example() {
  174. #[derive(Encode)]
  175. struct Transfer(AccountId, AccountId, u128);
  176. let mut runtime = build_solidity(
  177. r##"
  178. contract Erc20 {
  179. event Transfer(
  180. address indexed from,
  181. address indexed to,
  182. uint128 value
  183. );
  184. function emit_event(address from, address to, uint128 value) public {
  185. emit Transfer(from, to, value);
  186. }
  187. }"##,
  188. );
  189. runtime.constructor(0, Vec::new());
  190. let from = AccountId::from([1; 32]);
  191. let to = AccountId::from([2; 32]);
  192. let value = 10;
  193. runtime.function("emit_event", Transfer(from, to, value).encode());
  194. assert_eq!(runtime.events().len(), 1);
  195. let event = &runtime.events()[0];
  196. assert_eq!(event.data, Transfer(from, to, value).encode());
  197. assert_eq!(event.topics.len(), 3);
  198. assert_eq!(
  199. event.topics[0],
  200. event_topic("Transfer(address,address,uint128)")
  201. );
  202. assert_eq!(event.topics[1], topic_hash(&from.encode()));
  203. assert_eq!(event.topics[2], topic_hash(&to.encode()));
  204. }
  205. #[test]
  206. fn freestanding() {
  207. let mut runtime = build_solidity(
  208. r##"
  209. event A(bool indexed b);
  210. function foo() {
  211. emit A(true);
  212. }
  213. contract a {
  214. function emit_event() public {
  215. foo();
  216. }
  217. }"##,
  218. );
  219. runtime.constructor(0, Vec::new());
  220. runtime.function("emit_event", Vec::new());
  221. assert_eq!(runtime.events().len(), 1);
  222. let event = &runtime.events()[0];
  223. assert_eq!(event.data, true.encode());
  224. assert_eq!(event.topics[0], event_topic("A(bool)"));
  225. assert_eq!(event.topics[1], topic_hash(&true.encode()));
  226. }
  227. #[test]
  228. fn different_contract() {
  229. let mut runtime = build_solidity(
  230. r##"abstract contract A { event X(bool indexed foo); }
  231. contract B { function emit_event() public { emit A.X(true); } }"##,
  232. );
  233. runtime.constructor(0, Vec::new());
  234. runtime.function("emit_event", Vec::new());
  235. assert_eq!(runtime.events().len(), 1);
  236. let event = &runtime.events()[0];
  237. assert_eq!(event.data, true.encode());
  238. assert_eq!(event.topics[0], event_topic("X(bool)"));
  239. assert_eq!(event.topics[1], topic_hash(&true.encode()));
  240. }