polkadot.rs 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072
  1. // SPDX-License-Identifier: Apache-2.0
  2. /// Mock runtime for the contracts pallet.
  3. use blake2_rfc::blake2b::blake2b;
  4. use contract_metadata::ContractMetadata;
  5. use ink_metadata::InkProject;
  6. use ink_primitives::Hash;
  7. use parity_scale_codec::Decode;
  8. use sha2::{Digest, Sha256};
  9. use std::collections::HashSet;
  10. use std::{collections::HashMap, ffi::OsStr, fmt, fmt::Write};
  11. use tiny_keccak::{Hasher, Keccak};
  12. use wasmi::core::{HostError, Trap, TrapCode};
  13. use wasmi::{Engine, Error, Instance, Linker, Memory, MemoryType, Module, Store};
  14. use solang::codegen::Options;
  15. use solang::file_resolver::FileResolver;
  16. use solang::{compile, Target};
  17. use wasm_host_attr::wasm_host;
  18. mod polkadot_tests;
  19. type StorageKey = [u8; 32];
  20. type Address = [u8; 32];
  21. #[derive(Clone, Copy)]
  22. enum CallFlags {
  23. ForwardInput = 1,
  24. CloneInput = 2,
  25. TailCall = 4,
  26. AllowReentry = 8,
  27. }
  28. impl CallFlags {
  29. /// Returns true if this flag is set in the given `flags`.
  30. fn set(&self, flags: u32) -> bool {
  31. flags & *self as u32 != 0
  32. }
  33. }
  34. /// Reason for halting execution. Same as in pallet contracts.
  35. #[derive(Default, Debug, Clone)]
  36. enum HostReturn {
  37. /// The contract was terminated (deleted).
  38. #[default]
  39. Terminate,
  40. /// Flags and data returned by the contract.
  41. Data(u32, Vec<u8>),
  42. }
  43. impl HostReturn {
  44. fn as_data(&self) -> (u32, Vec<u8>) {
  45. match self {
  46. HostReturn::Data(flags, data) => (*flags, data.to_vec()),
  47. HostReturn::Terminate => (0, vec![]),
  48. }
  49. }
  50. }
  51. impl fmt::Display for HostReturn {
  52. fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
  53. match self {
  54. Self::Terminate => write!(f, "return: terminate"),
  55. Self::Data(flags, data) => write!(f, "return {flags} {data:?}"),
  56. }
  57. }
  58. }
  59. impl HostError for HostReturn {}
  60. /// Represents a contract code artifact.
  61. #[derive(Clone)]
  62. pub struct WasmCode {
  63. /// A mapping from function names to selectors.
  64. messages: HashMap<String, Vec<u8>>,
  65. /// A list of the selectors of the constructors.
  66. constructors: Vec<Vec<u8>>,
  67. hash: Hash,
  68. blob: Vec<u8>,
  69. }
  70. impl WasmCode {
  71. fn new(abi: &str, code: &[u8]) -> Self {
  72. let abi = load_abi(abi);
  73. let messages = abi
  74. .spec()
  75. .messages()
  76. .iter()
  77. .map(|f| (f.label().to_string(), f.selector().to_bytes().to_vec()))
  78. .collect();
  79. let constructors = abi
  80. .spec()
  81. .constructors()
  82. .iter()
  83. .map(|f| f.selector().to_bytes().to_vec())
  84. .collect();
  85. Self {
  86. messages,
  87. constructors,
  88. hash: blake2b(32, &[], code).as_bytes().try_into().unwrap(),
  89. blob: code.to_vec(),
  90. }
  91. }
  92. }
  93. /// A `Contract` represent deployed Wasm code with its storage which can be executed.
  94. #[derive(Clone)]
  95. pub struct Contract {
  96. code: WasmCode,
  97. storage: HashMap<StorageKey, Vec<u8>>,
  98. }
  99. impl From<WasmCode> for Contract {
  100. fn from(code: WasmCode) -> Self {
  101. Self {
  102. code,
  103. storage: HashMap::new(),
  104. }
  105. }
  106. }
  107. impl Contract {
  108. /// Instantiate this contract as a Wasm module for execution.
  109. fn instantiate(&self, runtime: Runtime) -> Result<(Store<Runtime>, Instance), Error> {
  110. let engine = Engine::default();
  111. let mut store = Store::new(&engine, runtime);
  112. let mut linker = <Linker<Runtime>>::new(&engine);
  113. Runtime::define(&mut store, &mut linker);
  114. let memory = Memory::new(&mut store, MemoryType::new(16, Some(16)).unwrap()).unwrap();
  115. linker.define("env", "memory", memory).unwrap();
  116. store.data_mut().memory = Some(memory);
  117. let instance = linker
  118. .instantiate(&mut store, &Module::new(&engine, &mut &self.code.blob[..])?)?
  119. .ensure_no_start(&mut store)
  120. .expect("we never emit a start function");
  121. Ok((store, instance))
  122. }
  123. /// Execute this contract at the exportet function `name` in the given `runtime` context.
  124. ///
  125. /// On success, returns the Wasm store including the runtime state is returned.
  126. /// On failure, returns the Wasm execution Error together with the debug buffer.
  127. #[allow(clippy::result_large_err)] // eDONTCARE
  128. fn execute(&self, name: &str, runtime: Runtime) -> Result<Store<Runtime>, (Error, String)> {
  129. let (mut store, instance) = self.instantiate(runtime).map_err(|e| (e, String::new()))?;
  130. match instance
  131. .get_export(&store, name)
  132. .and_then(|export| export.into_func())
  133. .unwrap_or_else(|| panic!("contract does not export '{name}'"))
  134. .call(&mut store, &[], &mut [])
  135. {
  136. Err(Error::Trap(trap)) if trap.trap_code().is_some() => {
  137. Err((Error::Trap(trap), store.data().debug_buffer.clone()))
  138. }
  139. Err(Error::Trap(trap)) => match trap.downcast::<HostReturn>() {
  140. Some(HostReturn::Data(flags, data)) => {
  141. store.data_mut().output = HostReturn::Data(flags, data);
  142. Ok(store)
  143. }
  144. Some(HostReturn::Terminate) => Ok(store),
  145. _ => panic!("contract execution stopped by unexpected trap"),
  146. },
  147. Err(e) => panic!("unexpected error during contract execution: {e}"),
  148. Ok(_) => Ok(store),
  149. }
  150. }
  151. }
  152. /// If contract is `Some`, this is considered to be a "contract account".
  153. #[derive(Default, Clone)]
  154. struct Account {
  155. address: Address,
  156. value: u128,
  157. contract: Option<Contract>,
  158. }
  159. impl PartialEq for Account {
  160. fn eq(&self, other: &Self) -> bool {
  161. self.address == other.address
  162. }
  163. }
  164. impl Account {
  165. /// Create a new contract account.
  166. /// The account address is derived based of the provided `salt`.
  167. fn with_contract(salt: &[u8], code: &WasmCode) -> Self {
  168. Self {
  169. address: Address::try_from(blake2b(32, &[], salt).as_bytes()).unwrap(),
  170. contract: Some(code.clone().into()),
  171. ..Default::default()
  172. }
  173. }
  174. }
  175. #[derive(Clone)]
  176. pub struct Event {
  177. pub data: Vec<u8>,
  178. pub topics: Vec<Hash>,
  179. }
  180. /// The runtime provides the state of the mocked blockchain node during contract execution.
  181. #[derive(Default, Clone)]
  182. struct Runtime {
  183. /// A list of "existing" accounts.
  184. accounts: Vec<Account>,
  185. /// A list of known ("uploaded") Wasm contract blobs.
  186. blobs: Vec<WasmCode>,
  187. /// Index into accounts pointing the account that is being executed.
  188. account: usize,
  189. /// Index into accounts pointing to the calling account.
  190. caller_account: usize,
  191. /// Will hold the memory reference after a successful execution.
  192. memory: Option<Memory>,
  193. /// The input for the contract execution.
  194. input: Option<Vec<u8>>,
  195. /// The output of the contract execution.
  196. output: HostReturn,
  197. /// Descirbes how much value was given to the contract call.
  198. transferred_value: u128,
  199. /// Combined ouptut of all `seal_debug_message` calls
  200. debug_buffer: String,
  201. /// Stores all events emitted during contract execution.
  202. events: Vec<Event>,
  203. /// The set of called events, needed for reentrancy protection.
  204. called_accounts: HashSet<usize>,
  205. }
  206. impl Runtime {
  207. fn new(blobs: Vec<WasmCode>) -> Self {
  208. Self {
  209. accounts: blobs
  210. .iter()
  211. .map(|blob| Account::with_contract(blob.hash.as_ref(), blob))
  212. .collect(),
  213. blobs,
  214. ..Default::default()
  215. }
  216. }
  217. /// Create a suitable runtime context based on the current one.
  218. ///
  219. /// Each contract execution must live within it's own runtime context.
  220. /// When calling into another contract, we must:
  221. /// * switch out the caller and callee account
  222. /// * populate the input and the transferred balance
  223. /// * clear the output
  224. fn new_context(&self, callee: usize, input: Vec<u8>, value: u128) -> Self {
  225. let mut runtime = self.clone();
  226. runtime.caller_account = self.account;
  227. runtime.account = callee;
  228. runtime.transferred_value = value;
  229. runtime.accounts[callee].value += value;
  230. runtime.input = Some(input);
  231. runtime.output = Default::default();
  232. runtime.called_accounts.insert(self.caller_account);
  233. runtime
  234. }
  235. /// After a succesfull contract execution, merge the runtime context of the callee back.
  236. ///
  237. /// We take over accounts (the callee might deploy new ones), debug buffer and emitted events.
  238. /// The transferred balance will now be deducted from the caller.
  239. fn accept_state(&mut self, callee_state: Self, transferred_value: u128) {
  240. self.debug_buffer = callee_state.debug_buffer;
  241. self.events = callee_state.events;
  242. self.accounts = callee_state.accounts;
  243. self.accounts[self.caller_account].value -= transferred_value;
  244. }
  245. /// Access the contract that is currently being executed.
  246. fn contract(&mut self) -> &mut Contract {
  247. self.accounts[self.account].contract.as_mut().unwrap()
  248. }
  249. /// Call an exported function under the account found at index `callee`.
  250. ///
  251. /// Returns `None` if the account has no contract.
  252. fn call(
  253. &mut self,
  254. export: &str,
  255. callee: usize,
  256. input: Vec<u8>,
  257. value: u128,
  258. ) -> Option<Result<Store<Runtime>, Error>> {
  259. println!(
  260. "{export}: account={} input={} value={value}",
  261. hex::encode(self.accounts[callee].address),
  262. hex::encode(&input)
  263. );
  264. self.accounts[callee]
  265. .contract
  266. .as_ref()?
  267. .execute(export, self.new_context(callee, input, value))
  268. .map_err(|(err, debug_buffer)| {
  269. self.debug_buffer = debug_buffer;
  270. err
  271. })
  272. .into()
  273. }
  274. /// Add a new contract account and call its "deploy" function accordingly.
  275. ///
  276. /// Returns `None` if there is no contract corresponding to the given `code_hash`.
  277. fn deploy(
  278. &mut self,
  279. code_hash: Hash,
  280. value: u128,
  281. salt: &[u8],
  282. input: Vec<u8>,
  283. ) -> Option<Result<Store<Runtime>, Error>> {
  284. let account = self
  285. .blobs
  286. .iter()
  287. .find(|code| code.hash == code_hash)
  288. .map(|code| Account::with_contract(salt, code))?;
  289. if self.accounts.contains(&account) {
  290. return Some(Err(Error::Trap(TrapCode::UnreachableCodeReached.into())));
  291. }
  292. self.accounts.push(account);
  293. self.call("deploy", self.accounts.len() - 1, input, value)
  294. }
  295. }
  296. fn read_len(mem: &[u8], ptr: u32) -> usize {
  297. u32::from_le_bytes(mem[ptr as usize..ptr as usize + 4].try_into().unwrap()) as usize
  298. }
  299. fn write_buf(mem: &mut [u8], ptr: u32, buf: &[u8]) {
  300. mem[ptr as usize..ptr as usize + buf.len()].copy_from_slice(buf);
  301. }
  302. fn read_buf(mem: &[u8], ptr: u32, len: u32) -> Vec<u8> {
  303. mem[ptr as usize..(ptr + len) as usize].to_vec()
  304. }
  305. fn read_value(mem: &[u8], ptr: u32) -> u128 {
  306. u128::from_le_bytes(read_buf(mem, ptr, 16).try_into().unwrap())
  307. }
  308. fn read_account(mem: &[u8], ptr: u32) -> Address {
  309. Address::try_from(&mem[ptr as usize..(ptr + 32) as usize]).unwrap()
  310. }
  311. fn read_hash(mem: &[u8], ptr: u32) -> Hash {
  312. Hash::try_from(&mem[ptr as usize..(ptr + 32) as usize]).unwrap()
  313. }
  314. /// Host functions mock the original implementation, refer to the [pallet docs][1] for more information.
  315. ///
  316. /// [1]: https://docs.rs/pallet-contracts/latest/pallet_contracts/api_doc/index.html
  317. #[wasm_host]
  318. impl Runtime {
  319. #[seal(0)]
  320. fn input(dest_ptr: u32, len_ptr: u32) -> Result<(), Trap> {
  321. let data = vm.input.as_ref().expect("input was forwarded");
  322. assert!(read_len(mem, len_ptr) >= data.len());
  323. println!("seal_input: {}", hex::encode(data));
  324. write_buf(mem, dest_ptr, data);
  325. write_buf(mem, len_ptr, &(data.len() as u32).to_le_bytes());
  326. Ok(())
  327. }
  328. #[seal(0)]
  329. fn seal_return(flags: u32, data_ptr: u32, data_len: u32) -> Result<(), Trap> {
  330. let output = read_buf(mem, data_ptr, data_len);
  331. println!("seal_return: {flags} {}", hex::encode(&output));
  332. Err(HostReturn::Data(flags, output).into())
  333. }
  334. #[seal(0)]
  335. fn value_transferred(dest_ptr: u32, out_len_ptr: u32) -> Result<(), Trap> {
  336. let value = vm.transferred_value.to_le_bytes();
  337. assert!(read_len(mem, out_len_ptr) >= value.len());
  338. println!("seal_value_transferred: {}", vm.transferred_value);
  339. write_buf(mem, dest_ptr, &value);
  340. write_buf(mem, out_len_ptr, &(value.len() as u32).to_le_bytes());
  341. Ok(())
  342. }
  343. #[seal(0)]
  344. fn debug_message(data_ptr: u32, len: u32) -> Result<u32, Trap> {
  345. let buf = read_buf(mem, data_ptr, len);
  346. let msg = std::str::from_utf8(&buf).expect("seal_debug_message: Invalid UFT8");
  347. println!("seal_debug_message: {msg}");
  348. vm.debug_buffer.push_str(msg);
  349. Ok(0)
  350. }
  351. #[seal(1)]
  352. fn get_storage(
  353. key_ptr: u32,
  354. key_len: u32,
  355. out_ptr: u32,
  356. out_len_ptr: u32,
  357. ) -> Result<u32, Trap> {
  358. let key = StorageKey::try_from(read_buf(mem, key_ptr, key_len))
  359. .expect("storage key size must be 32 bytes");
  360. let value = match vm.contract().storage.get(&key) {
  361. Some(value) => value,
  362. _ => return Ok(3), // In pallet-contracts, ReturnCode::KeyNotFound == 3
  363. };
  364. println!("get_storage: {}={}", hex::encode(key), hex::encode(value));
  365. write_buf(mem, out_ptr, value);
  366. write_buf(mem, out_len_ptr, &(value.len() as u32).to_le_bytes());
  367. Ok(0)
  368. }
  369. #[seal(2)]
  370. fn set_storage(
  371. key_ptr: u32,
  372. key_len: u32,
  373. value_ptr: u32,
  374. value_len: u32,
  375. ) -> Result<u32, Trap> {
  376. let key = StorageKey::try_from(read_buf(mem, key_ptr, key_len))
  377. .expect("storage key size must be 32 bytes");
  378. let value = mem[value_ptr as usize..(value_ptr + value_len) as usize].to_vec();
  379. println!("set_storage: {}={}", hex::encode(key), hex::encode(&value));
  380. match vm.contract().storage.insert(key, value) {
  381. Some(value) => Ok(value.len() as u32),
  382. _ => Ok(u32::MAX), // In pallets contract, u32::MAX is the "none sentinel"
  383. }
  384. }
  385. #[seal(1)]
  386. fn clear_storage(key_ptr: u32, key_len: u32) -> Result<u32, Trap> {
  387. let key = StorageKey::try_from(read_buf(mem, key_ptr, key_len))
  388. .expect("storage key size must be 32 bytes");
  389. println!("clear_storage: {}", hex::encode(key));
  390. match vm.contract().storage.remove(&key) {
  391. Some(value) => Ok(value.len() as u32),
  392. _ => Ok(u32::MAX), // In pallets contract, u32::MAX is the "none sentinel"
  393. }
  394. }
  395. #[seal(0)]
  396. fn hash_keccak_256(input_ptr: u32, input_len: u32, output_ptr: u32) -> Result<(), Trap> {
  397. let mut hasher = Keccak::v256();
  398. hasher.update(&read_buf(mem, input_ptr, input_len));
  399. hasher.finalize(&mut mem[output_ptr as usize..(output_ptr + 32) as usize]);
  400. Ok(())
  401. }
  402. #[seal(0)]
  403. fn hash_sha2_256(input_ptr: u32, input_len: u32, output_ptr: u32) -> Result<(), Trap> {
  404. let mut hasher = Sha256::new();
  405. hasher.update(read_buf(mem, input_ptr, input_len));
  406. write_buf(mem, output_ptr, &hasher.finalize());
  407. Ok(())
  408. }
  409. #[seal(0)]
  410. fn hash_blake2_128(input_ptr: u32, input_len: u32, output_ptr: u32) -> Result<(), Trap> {
  411. let data = read_buf(mem, input_ptr, input_len);
  412. write_buf(mem, output_ptr, blake2b(16, &[], &data).as_bytes());
  413. Ok(())
  414. }
  415. #[seal(0)]
  416. fn hash_blake2_256(input_ptr: u32, input_len: u32, output_ptr: u32) -> Result<(), Trap> {
  417. let data = read_buf(mem, input_ptr, input_len);
  418. write_buf(mem, output_ptr, blake2b(32, &[], &data).as_bytes());
  419. Ok(())
  420. }
  421. #[seal(1)]
  422. fn seal_call(
  423. flags: u32,
  424. callee_ptr: u32,
  425. _gas: u64,
  426. value_ptr: u32,
  427. input_ptr: u32,
  428. input_len: u32,
  429. output_ptr: u32,
  430. output_len_ptr: u32,
  431. ) -> Result<u32, Trap> {
  432. assert!(flags <= 0b1111);
  433. let input = if CallFlags::ForwardInput.set(flags) {
  434. if vm.input.is_none() {
  435. return Ok(1);
  436. }
  437. vm.input.take().unwrap()
  438. } else if CallFlags::CloneInput.set(flags) {
  439. if vm.input.is_none() {
  440. return Ok(1);
  441. }
  442. vm.input.as_ref().unwrap().clone()
  443. } else {
  444. read_buf(mem, input_ptr, input_len)
  445. };
  446. let value = read_value(mem, value_ptr);
  447. let callee_address = read_account(mem, callee_ptr);
  448. let callee = match vm
  449. .accounts
  450. .iter()
  451. .enumerate()
  452. .find(|(_, account)| account.address == callee_address)
  453. .map(|(index, _)| index)
  454. {
  455. Some(index) => index,
  456. None => return Ok(8), // ReturnCode::NotCallable
  457. };
  458. if vm.called_accounts.contains(&callee) && !CallFlags::AllowReentry.set(flags) {
  459. return Ok(1);
  460. }
  461. if value > vm.accounts[vm.account].value {
  462. return Ok(5); // ReturnCode::TransferFailed
  463. }
  464. let ((ret, data), state) = match vm.call("call", callee, input, value) {
  465. Some(Ok(state)) => ((state.data().output.as_data()), state),
  466. Some(Err(_)) => return Ok(1), // ReturnCode::CalleeTrapped
  467. None => return Ok(8),
  468. };
  469. if CallFlags::TailCall.set(flags) {
  470. return Err(HostReturn::Data(ret, data).into());
  471. }
  472. if output_len_ptr != u32::MAX {
  473. assert!(read_len(mem, output_len_ptr) >= data.len());
  474. write_buf(mem, output_ptr, &data);
  475. write_buf(mem, output_len_ptr, &(data.len() as u32).to_le_bytes());
  476. }
  477. if ret == 0 {
  478. vm.accept_state(state.into_data(), value);
  479. return Ok(0);
  480. }
  481. Ok(2) // Callee reverted
  482. }
  483. #[seal(0)]
  484. fn instantiation_nonce() -> Result<u64, Trap> {
  485. Ok(vm.accounts.len() as u64)
  486. }
  487. #[seal(0)]
  488. fn minimum_balance(out_ptr: u32, out_len_ptr: u32) -> Result<(), Trap> {
  489. assert!(read_len(mem, out_len_ptr) >= 16);
  490. write_buf(mem, out_ptr, &500u128.to_le_bytes());
  491. Ok(())
  492. }
  493. #[seal(1)]
  494. fn instantiate(
  495. code_hash_ptr: u32,
  496. _gas: u64,
  497. value_ptr: u32,
  498. input_data_ptr: u32,
  499. input_data_len: u32,
  500. address_ptr: u32,
  501. address_len_ptr: u32,
  502. output_ptr: u32,
  503. output_len_ptr: u32,
  504. salt_ptr: u32,
  505. salt_len: u32,
  506. ) -> Result<u32, Trap> {
  507. let code_hash = read_hash(mem, code_hash_ptr);
  508. let salt = read_buf(mem, salt_ptr, salt_len);
  509. let input = read_buf(mem, input_data_ptr, input_data_len);
  510. let value = read_value(mem, value_ptr);
  511. if value > vm.accounts[vm.account].value {
  512. return Ok(5); // ReturnCode::TransferFailed
  513. }
  514. let ((flags, data), state) = match vm.deploy(code_hash, value, &salt, input) {
  515. Some(Ok(state)) => ((state.data().output.as_data()), state),
  516. Some(Err(_)) => return Ok(1), // ReturnCode::CalleeTrapped
  517. None => return Ok(7), // ReturnCode::CodeNotFound
  518. };
  519. if output_len_ptr != u32::MAX {
  520. write_buf(mem, output_ptr, &data);
  521. write_buf(mem, output_len_ptr, &(data.len() as u32).to_le_bytes());
  522. }
  523. let address = state.data().accounts.last().unwrap().address;
  524. write_buf(mem, address_ptr, &address);
  525. write_buf(mem, address_len_ptr, &(address.len() as u32).to_le_bytes());
  526. if flags == 0 {
  527. vm.accept_state(state.into_data(), value);
  528. return Ok(0);
  529. }
  530. Ok(2) // Callee reverted
  531. }
  532. #[seal(0)]
  533. fn transfer(
  534. account_ptr: u32,
  535. account_len: u32,
  536. value_ptr: u32,
  537. value_len: u32,
  538. ) -> Result<u32, Trap> {
  539. assert_eq!(account_len, 32);
  540. assert_eq!(value_len, 16);
  541. let value = read_value(mem, value_ptr);
  542. if value > vm.accounts[vm.account].value {
  543. return Ok(5); // ReturnCode::TransferFailed
  544. }
  545. let account = read_account(mem, account_ptr);
  546. if let Some(to) = vm.accounts.iter_mut().find(|c| c.address == account) {
  547. to.value += value;
  548. vm.accounts[vm.account].value -= value;
  549. return Ok(0);
  550. }
  551. Ok(5)
  552. }
  553. #[seal(0)]
  554. fn address(out_ptr: u32, out_len_ptr: u32) -> Result<(), Trap> {
  555. let address = vm.accounts[vm.account].address;
  556. let out_len = read_len(mem, out_len_ptr);
  557. assert!(out_len >= address.len());
  558. write_buf(mem, out_ptr, &address);
  559. write_buf(mem, out_len_ptr, &(address.len() as u32).to_le_bytes());
  560. Ok(())
  561. }
  562. #[seal(0)]
  563. fn caller(out_ptr: u32, out_len_ptr: u32) -> Result<(), Trap> {
  564. let out_len = read_len(mem, out_len_ptr);
  565. let address = vm.accounts[vm.caller_account].address;
  566. assert!(out_len >= address.len());
  567. write_buf(mem, out_ptr, &address);
  568. write_buf(mem, out_len_ptr, &(address.len() as u32).to_le_bytes());
  569. Ok(())
  570. }
  571. #[seal(0)]
  572. fn balance(out_ptr: u32, out_len_ptr: u32) -> Result<(), Trap> {
  573. let balance = vm.accounts[vm.account].value.to_le_bytes();
  574. let out_len = read_len(mem, out_len_ptr);
  575. assert!(out_len >= balance.len());
  576. write_buf(mem, out_ptr, &balance);
  577. write_buf(mem, out_len_ptr, &(balance.len() as u32).to_le_bytes());
  578. Ok(())
  579. }
  580. #[seal(0)]
  581. fn block_number(out_ptr: u32, out_len_ptr: u32) -> Result<(), Trap> {
  582. let block = 950_119_597u32.to_le_bytes();
  583. let out_len = read_len(mem, out_len_ptr);
  584. assert!(out_len >= block.len());
  585. write_buf(mem, out_ptr, &block);
  586. write_buf(mem, out_len_ptr, &(block.len() as u32).to_le_bytes());
  587. Ok(())
  588. }
  589. #[seal(0)]
  590. fn now(out_ptr: u32, out_len_ptr: u32) -> Result<(), Trap> {
  591. let now = 1594035638000u64.to_le_bytes();
  592. let out_len = read_len(mem, out_len_ptr);
  593. assert!(out_len >= now.len());
  594. write_buf(mem, out_ptr, &now);
  595. write_buf(mem, out_len_ptr, &(now.len() as u32).to_le_bytes());
  596. Ok(())
  597. }
  598. #[seal(0)]
  599. fn gas_left(out_ptr: u32, out_len_ptr: u32) -> Result<(), Trap> {
  600. let gas = 2_224_097_461u64.to_le_bytes();
  601. let out_len = read_len(mem, out_len_ptr);
  602. assert!(out_len >= gas.len());
  603. write_buf(mem, out_ptr, &gas);
  604. write_buf(mem, out_len_ptr, &(gas.len() as u32).to_le_bytes());
  605. Ok(())
  606. }
  607. #[seal(0)]
  608. fn weight_to_fee(gas: u64, out_ptr: u32, out_len_ptr: u32) -> Result<(), Trap> {
  609. let price = (59_541_253_813_967 * gas as u128).to_le_bytes();
  610. let out_len = read_len(mem, out_len_ptr);
  611. assert!(out_len >= price.len());
  612. write_buf(mem, out_ptr, &price);
  613. write_buf(mem, out_len_ptr, &(price.len() as u32).to_le_bytes());
  614. Ok(())
  615. }
  616. #[seal(1)]
  617. fn terminate(beneficiary_ptr: u32) -> Result<(), Trap> {
  618. let free = vm.accounts.remove(vm.account).value;
  619. let address = read_account(mem, beneficiary_ptr);
  620. println!("seal_terminate: {} gets {free}", hex::encode(address));
  621. if let Some(to) = vm.accounts.iter_mut().find(|a| a.address == address) {
  622. to.value += free;
  623. }
  624. Err(HostReturn::Terminate.into())
  625. }
  626. #[seal(0)]
  627. fn deposit_event(
  628. topics_ptr: u32,
  629. topics_len: u32,
  630. data_ptr: u32,
  631. data_len: u32,
  632. ) -> Result<(), Trap> {
  633. let data = read_buf(mem, data_ptr, data_len);
  634. let topics = if topics_len > 0 {
  635. <Vec<Hash>>::decode(&mut &read_buf(mem, topics_ptr, topics_len)[..]).unwrap()
  636. } else {
  637. vec![]
  638. };
  639. println!(
  640. "seal_deposit_event data: {} topics: {:?}",
  641. hex::encode(&data),
  642. topics.iter().map(hex::encode).collect::<Vec<_>>()
  643. );
  644. vm.events.push(Event { data, topics });
  645. Ok(())
  646. }
  647. /// Mock chain extension with ID 123 that writes the reversed input to the output buf.
  648. /// Returns the sum of the input data.
  649. #[seal(0)]
  650. fn call_chain_extension(
  651. id: u32,
  652. input_ptr: u32,
  653. input_len: u32,
  654. output_ptr: u32,
  655. output_len_ptr: u32,
  656. ) -> Result<u32, Trap> {
  657. assert_eq!(id, 123, "unkown chain extension");
  658. assert!(read_len(mem, output_len_ptr) == 16384 && input_len <= 16384);
  659. let mut data = read_buf(mem, input_ptr, input_len);
  660. data.reverse();
  661. write_buf(mem, output_ptr, &data);
  662. write_buf(mem, output_len_ptr, &(data.len() as u32).to_le_bytes());
  663. Ok(data.iter().map(|i| *i as u32).sum())
  664. }
  665. #[seal(0)]
  666. fn is_contract(input_ptr: u32) -> Result<u32, Trap> {
  667. let address = read_account(mem, input_ptr);
  668. Ok(vm
  669. .accounts
  670. .iter()
  671. .any(|account| account.contract.is_some() && account.address == address)
  672. .into())
  673. }
  674. #[seal(0)]
  675. fn set_code_hash(code_hash_ptr: u32) -> Result<u32, Trap> {
  676. let hash = read_hash(mem, code_hash_ptr);
  677. if let Some(code) = vm.blobs.iter().find(|code| code.hash == hash) {
  678. vm.accounts[vm.account].contract.as_mut().unwrap().code = code.clone();
  679. return Ok(0);
  680. }
  681. Ok(7) // ReturnCode::CodeNoteFound
  682. }
  683. }
  684. /// Provides a mock implementation of substrates [contracts pallet][1]
  685. ///
  686. /// [1]: https://docs.rs/pallet-contracts/latest/pallet_contracts/index.html
  687. pub struct MockSubstrate(Store<Runtime>);
  688. impl MockSubstrate {
  689. fn invoke(&mut self, export: &str, input: Vec<u8>) -> Result<(), Error> {
  690. let callee = self.0.data().account;
  691. let value = self.0.data().transferred_value;
  692. let runtime = self.0.data_mut();
  693. runtime.debug_buffer.clear();
  694. runtime.events.clear();
  695. runtime.called_accounts.clear();
  696. self.0 = runtime.call(export, callee, input, value).unwrap()?;
  697. self.0.data_mut().transferred_value = 0;
  698. Ok(())
  699. }
  700. /// Specify the caller account index for the next function or constructor call.
  701. pub fn set_account(&mut self, index: usize) {
  702. self.0.data_mut().account = index;
  703. }
  704. /// Specify the balance for the next function or constructor call.
  705. pub fn set_transferred_value(&mut self, amount: u128) {
  706. self.0.data_mut().transferred_value = amount;
  707. }
  708. /// Get the balance of the given `account`.
  709. pub fn balance(&self, account: usize) -> u128 {
  710. self.0.data().accounts[account].value
  711. }
  712. /// Get the address of the calling account.
  713. pub fn caller(&self) -> Address {
  714. self.0.data().accounts[self.0.data().caller_account].address
  715. }
  716. /// Get the output of the last function or constructor call.
  717. pub fn output(&self) -> Vec<u8> {
  718. if let HostReturn::Data(_, data) = &self.0.data().output {
  719. return data.to_vec();
  720. }
  721. vec![]
  722. }
  723. /// Get the debug buffer contents of the last function or constructor call.
  724. pub fn debug_buffer(&self) -> String {
  725. self.0.data().debug_buffer.clone()
  726. }
  727. /// Get the emitted events of the last function or constructor call.
  728. pub fn events(&self) -> Vec<Event> {
  729. self.0.data().events.clone()
  730. }
  731. /// Get a list of all deployed contracts.
  732. pub fn contracts(&self) -> Vec<&Contract> {
  733. self.0
  734. .data()
  735. .accounts
  736. .iter()
  737. .map(|a| a.contract.as_ref().unwrap())
  738. .collect()
  739. }
  740. /// Read the storage of the account that was (or is about to be) called.
  741. pub fn storage(&self) -> &HashMap<StorageKey, Vec<u8>> {
  742. &self.0.data().accounts[self.0.data().account]
  743. .contract
  744. .as_ref()
  745. .unwrap()
  746. .storage
  747. }
  748. /// Get the selector of the given `function_name` on the given `contract` index.
  749. pub fn selector(&self, contract: usize, function_name: &str) -> &[u8] {
  750. &self.0.data().blobs[contract].messages[function_name]
  751. }
  752. /// Execute the constructor `index` with the given input `args`.
  753. pub fn constructor(&mut self, index: usize, mut args: Vec<u8>) {
  754. let mut input = self.0.data().blobs[self.0.data().account].constructors[index].clone();
  755. input.append(&mut args);
  756. self.raw_constructor(input);
  757. }
  758. /// Get a list of all uploaded cotracts
  759. pub fn blobs(&self) -> Vec<WasmCode> {
  760. self.0.data().blobs.clone()
  761. }
  762. /// Call the "deploy" function with the given `input`.
  763. ///
  764. /// `input` must contain the selector fo the constructor.
  765. pub fn raw_constructor(&mut self, input: Vec<u8>) {
  766. self.invoke("deploy", input).unwrap();
  767. if let HostReturn::Data(flags, _) = self.0.data().output {
  768. assert!(flags == 0)
  769. }
  770. }
  771. /// Call the contract function `name` with the given input `args`.
  772. /// Panics if the contract traps or reverts.
  773. pub fn function(&mut self, name: &str, mut args: Vec<u8>) {
  774. let mut input = self.0.data().blobs[self.0.data().account].messages[name].clone();
  775. input.append(&mut args);
  776. self.raw_function(input);
  777. }
  778. /// Expect the contract function `name` with the given input `args` to trap or revert.
  779. ///
  780. /// Only traps caused by an `unreachable` instruction are allowed. Other traps will panic instead.
  781. pub fn function_expect_failure(&mut self, name: &str, mut args: Vec<u8>) {
  782. let mut input = self.0.data().blobs[self.0.data().account].messages[name].clone();
  783. input.append(&mut args);
  784. self.raw_function_failure(input);
  785. }
  786. /// Call the "deploy" function with the given `input`.
  787. ///
  788. /// `input` must contain the selector fo the constructor.
  789. pub fn raw_function(&mut self, input: Vec<u8>) {
  790. self.invoke("call", input).unwrap();
  791. if let HostReturn::Data(flags, _) = self.0.data().output {
  792. assert!(flags == 0)
  793. }
  794. }
  795. fn raw_failure(&mut self, export: &str, input: Vec<u8>) {
  796. match self.invoke(export, input) {
  797. Err(wasmi::Error::Trap(trap)) => match trap.trap_code() {
  798. Some(TrapCode::UnreachableCodeReached) => (),
  799. _ => panic!("trap: {trap:?}"),
  800. },
  801. Err(err) => panic!("unexpected error: {err:?}"),
  802. Ok(_) => match self.0.data().output {
  803. HostReturn::Data(1, _) => (),
  804. _ => panic!("unexpected return from main"),
  805. },
  806. }
  807. }
  808. /// Call the "call" function with the given input and expect the contract to trap.
  809. ///
  810. /// `input` must contain the desired function selector.
  811. ///
  812. /// Only traps caused by an `unreachable` instruction are allowed. Other traps will panic instead.
  813. pub fn raw_function_failure(&mut self, input: Vec<u8>) {
  814. self.raw_failure("call", input);
  815. }
  816. /// Call the "deploy" function with the given input and expect the contract to trap.
  817. ///
  818. /// `input` must contain the desired function selector.
  819. ///
  820. /// Only traps caused by an `unreachable` instruction are allowed. Other traps will panic instead.
  821. pub fn raw_constructor_failure(&mut self, input: Vec<u8>) {
  822. self.raw_failure("deploy", input);
  823. }
  824. pub fn heap_verify(&mut self) {
  825. let mem = self.0.data().memory.unwrap().data(&mut self.0);
  826. let memsize = mem.len();
  827. println!("memory size:{memsize}");
  828. let mut current_elem = 0x10000;
  829. let mut last_elem = 0u32;
  830. let read_u32 = |ptr| u32::from_le_bytes(mem[ptr..ptr + 4].try_into().unwrap());
  831. loop {
  832. let next: u32 = read_u32(current_elem);
  833. let prev: u32 = read_u32(current_elem + 4);
  834. let length: u32 = read_u32(current_elem + 8);
  835. let allocated: u32 = read_u32(current_elem + 12);
  836. println!("next:{next:08x} prev:{prev:08x} length:{length} allocated:{allocated}");
  837. let buf = read_buf(mem, current_elem as u32 + 16, length);
  838. if allocated == 0 {
  839. println!("{:08x} {} not allocated", current_elem + 16, length);
  840. } else {
  841. println!("{:08x} {} allocated", current_elem + 16, length);
  842. assert_eq!(allocated & 0xffff, 1);
  843. for offset in (0..buf.len()).step_by(16) {
  844. let mut hex = "\t".to_string();
  845. let mut chars = "\t".to_string();
  846. for i in 0..16 {
  847. if offset + i >= buf.len() {
  848. break;
  849. }
  850. let b = buf[offset + i];
  851. write!(hex, " {b:02x}").unwrap();
  852. if b.is_ascii() && !b.is_ascii_control() {
  853. write!(chars, " {}", b as char).unwrap();
  854. } else {
  855. chars.push_str(" ");
  856. }
  857. }
  858. println!("{hex}\n{chars}");
  859. }
  860. }
  861. assert_eq!(last_elem, prev);
  862. if next == 0 {
  863. break;
  864. }
  865. last_elem = current_elem as u32;
  866. current_elem = next as usize;
  867. }
  868. }
  869. }
  870. /// Build all contracts foud in `src` and set up a mock runtime.
  871. ///
  872. /// The mock runtime will contain a contract account for each contract in `src`.
  873. /// Constructors are _not_ called, therefore the storage will not be initialized.
  874. pub fn build_solidity(src: &str) -> MockSubstrate {
  875. build_solidity_with_options(src, false, true)
  876. }
  877. /// A variant of `MockSubstrate::uild_solidity()` with the ability to specify compiler options:
  878. /// * log_ret: enable logging of host function return codes
  879. /// * log_err: enable logging of runtime errors
  880. pub fn build_solidity_with_options(src: &str, log_ret: bool, log_err: bool) -> MockSubstrate {
  881. let blobs = build_wasm(src, log_ret, log_err)
  882. .iter()
  883. .map(|(code, abi)| WasmCode::new(abi, code))
  884. .collect();
  885. MockSubstrate(Store::new(&Engine::default(), Runtime::new(blobs)))
  886. }
  887. pub fn build_wasm(src: &str, log_ret: bool, log_err: bool) -> Vec<(Vec<u8>, String)> {
  888. let tmp_file = OsStr::new("test.sol");
  889. let mut cache = FileResolver::default();
  890. cache.set_file_contents(tmp_file.to_str().unwrap(), src.to_string());
  891. let opt = inkwell::OptimizationLevel::Default;
  892. let target = Target::default_polkadot();
  893. let (wasm, ns) = compile(
  894. tmp_file,
  895. &mut cache,
  896. target,
  897. &Options {
  898. opt_level: opt.into(),
  899. log_api_return_codes: log_ret,
  900. log_runtime_errors: log_err,
  901. log_prints: true,
  902. #[cfg(feature = "wasm_opt")]
  903. wasm_opt: Some(contract_build::OptimizationPasses::Z),
  904. ..Default::default()
  905. },
  906. vec!["unknown".to_string()],
  907. "0.0.1",
  908. );
  909. ns.print_diagnostics_in_plain(&cache, false);
  910. assert!(!wasm.is_empty());
  911. wasm
  912. }
  913. pub fn load_abi(s: &str) -> InkProject {
  914. let bundle = serde_json::from_str::<ContractMetadata>(s).unwrap();
  915. serde_json::from_value::<InkProject>(serde_json::to_value(bundle.abi).unwrap()).unwrap()
  916. }