substrate.rs 32 KB

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