substrate.rs 35 KB

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