polkadot.rs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083
  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 exported 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. /// Describes how much value was given to the contract call.
  198. transferred_value: u128,
  199. /// Combined output 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 successful 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. ///
  318. /// Address `[0; u8]` is considered the root account.
  319. #[wasm_host]
  320. impl Runtime {
  321. #[seal(0)]
  322. fn input(dest_ptr: u32, len_ptr: u32) -> Result<(), Trap> {
  323. let data = vm.input.as_ref().expect("input was forwarded");
  324. assert!(read_len(mem, len_ptr) >= data.len());
  325. println!("seal_input: {}", hex::encode(data));
  326. write_buf(mem, dest_ptr, data);
  327. write_buf(mem, len_ptr, &(data.len() as u32).to_le_bytes());
  328. Ok(())
  329. }
  330. #[seal(0)]
  331. fn seal_return(flags: u32, data_ptr: u32, data_len: u32) -> Result<(), Trap> {
  332. let output = read_buf(mem, data_ptr, data_len);
  333. println!("seal_return: {flags} {}", hex::encode(&output));
  334. Err(HostReturn::Data(flags, output).into())
  335. }
  336. #[seal(0)]
  337. fn value_transferred(dest_ptr: u32, out_len_ptr: u32) -> Result<(), Trap> {
  338. let value = vm.transferred_value.to_le_bytes();
  339. assert!(read_len(mem, out_len_ptr) >= value.len());
  340. println!("seal_value_transferred: {}", vm.transferred_value);
  341. write_buf(mem, dest_ptr, &value);
  342. write_buf(mem, out_len_ptr, &(value.len() as u32).to_le_bytes());
  343. Ok(())
  344. }
  345. #[seal(0)]
  346. fn debug_message(data_ptr: u32, len: u32) -> Result<u32, Trap> {
  347. let buf = read_buf(mem, data_ptr, len);
  348. let msg = std::str::from_utf8(&buf).expect("seal_debug_message: Invalid UFT8");
  349. println!("seal_debug_message: {msg}");
  350. vm.debug_buffer.push_str(msg);
  351. Ok(0)
  352. }
  353. #[seal(1)]
  354. fn get_storage(
  355. key_ptr: u32,
  356. key_len: u32,
  357. out_ptr: u32,
  358. out_len_ptr: u32,
  359. ) -> Result<u32, Trap> {
  360. let key = StorageKey::try_from(read_buf(mem, key_ptr, key_len))
  361. .expect("storage key size must be 32 bytes");
  362. let value = match vm.contract().storage.get(&key) {
  363. Some(value) => value,
  364. _ => return Ok(3), // In pallet-contracts, ReturnCode::KeyNotFound == 3
  365. };
  366. println!("get_storage: {}={}", hex::encode(key), hex::encode(value));
  367. write_buf(mem, out_ptr, value);
  368. write_buf(mem, out_len_ptr, &(value.len() as u32).to_le_bytes());
  369. Ok(0)
  370. }
  371. #[seal(2)]
  372. fn set_storage(
  373. key_ptr: u32,
  374. key_len: u32,
  375. value_ptr: u32,
  376. value_len: u32,
  377. ) -> Result<u32, Trap> {
  378. let key = StorageKey::try_from(read_buf(mem, key_ptr, key_len))
  379. .expect("storage key size must be 32 bytes");
  380. let value = mem[value_ptr as usize..(value_ptr + value_len) as usize].to_vec();
  381. println!("set_storage: {}={}", hex::encode(key), hex::encode(&value));
  382. match vm.contract().storage.insert(key, value) {
  383. Some(value) => Ok(value.len() as u32),
  384. _ => Ok(u32::MAX), // In pallets contract, u32::MAX is the "none sentinel"
  385. }
  386. }
  387. #[seal(1)]
  388. fn clear_storage(key_ptr: u32, key_len: u32) -> Result<u32, Trap> {
  389. let key = StorageKey::try_from(read_buf(mem, key_ptr, key_len))
  390. .expect("storage key size must be 32 bytes");
  391. println!("clear_storage: {}", hex::encode(key));
  392. match vm.contract().storage.remove(&key) {
  393. Some(value) => Ok(value.len() as u32),
  394. _ => Ok(u32::MAX), // In pallets contract, u32::MAX is the "none sentinel"
  395. }
  396. }
  397. #[seal(0)]
  398. fn hash_keccak_256(input_ptr: u32, input_len: u32, output_ptr: u32) -> Result<(), Trap> {
  399. let mut hasher = Keccak::v256();
  400. hasher.update(&read_buf(mem, input_ptr, input_len));
  401. hasher.finalize(&mut mem[output_ptr as usize..(output_ptr + 32) as usize]);
  402. Ok(())
  403. }
  404. #[seal(0)]
  405. fn hash_sha2_256(input_ptr: u32, input_len: u32, output_ptr: u32) -> Result<(), Trap> {
  406. let mut hasher = Sha256::new();
  407. hasher.update(read_buf(mem, input_ptr, input_len));
  408. write_buf(mem, output_ptr, &hasher.finalize());
  409. Ok(())
  410. }
  411. #[seal(0)]
  412. fn hash_blake2_128(input_ptr: u32, input_len: u32, output_ptr: u32) -> Result<(), Trap> {
  413. let data = read_buf(mem, input_ptr, input_len);
  414. write_buf(mem, output_ptr, blake2b(16, &[], &data).as_bytes());
  415. Ok(())
  416. }
  417. #[seal(0)]
  418. fn hash_blake2_256(input_ptr: u32, input_len: u32, output_ptr: u32) -> Result<(), Trap> {
  419. let data = read_buf(mem, input_ptr, input_len);
  420. write_buf(mem, output_ptr, blake2b(32, &[], &data).as_bytes());
  421. Ok(())
  422. }
  423. #[seal(1)]
  424. fn seal_call(
  425. flags: u32,
  426. callee_ptr: u32,
  427. _gas: u64,
  428. value_ptr: u32,
  429. input_ptr: u32,
  430. input_len: u32,
  431. output_ptr: u32,
  432. output_len_ptr: u32,
  433. ) -> Result<u32, Trap> {
  434. assert!(flags <= 0b1111);
  435. let input = if CallFlags::ForwardInput.set(flags) {
  436. if vm.input.is_none() {
  437. return Ok(1);
  438. }
  439. vm.input.take().unwrap()
  440. } else if CallFlags::CloneInput.set(flags) {
  441. if vm.input.is_none() {
  442. return Ok(1);
  443. }
  444. vm.input.as_ref().unwrap().clone()
  445. } else {
  446. read_buf(mem, input_ptr, input_len)
  447. };
  448. let value = read_value(mem, value_ptr);
  449. let callee_address = read_account(mem, callee_ptr);
  450. let callee = match vm
  451. .accounts
  452. .iter()
  453. .enumerate()
  454. .find(|(_, account)| account.address == callee_address)
  455. .map(|(index, _)| index)
  456. {
  457. Some(index) => index,
  458. None => return Ok(8), // ReturnCode::NotCallable
  459. };
  460. if vm.called_accounts.contains(&callee) && !CallFlags::AllowReentry.set(flags) {
  461. return Ok(1);
  462. }
  463. if value > vm.accounts[vm.account].value {
  464. return Ok(5); // ReturnCode::TransferFailed
  465. }
  466. let ((ret, data), state) = match vm.call("call", callee, input, value) {
  467. Some(Ok(state)) => ((state.data().output.as_data()), state),
  468. Some(Err(_)) => return Ok(1), // ReturnCode::CalleeTrapped
  469. None => return Ok(8),
  470. };
  471. if CallFlags::TailCall.set(flags) {
  472. return Err(HostReturn::Data(ret, data).into());
  473. }
  474. if output_len_ptr != u32::MAX {
  475. assert!(read_len(mem, output_len_ptr) >= data.len());
  476. write_buf(mem, output_ptr, &data);
  477. write_buf(mem, output_len_ptr, &(data.len() as u32).to_le_bytes());
  478. }
  479. if ret == 0 {
  480. vm.accept_state(state.into_data(), value);
  481. return Ok(0);
  482. }
  483. Ok(2) // Callee reverted
  484. }
  485. #[seal(0)]
  486. fn instantiation_nonce() -> Result<u64, Trap> {
  487. Ok(vm.accounts.len() as u64)
  488. }
  489. #[seal(0)]
  490. fn minimum_balance(out_ptr: u32, out_len_ptr: u32) -> Result<(), Trap> {
  491. assert!(read_len(mem, out_len_ptr) >= 16);
  492. write_buf(mem, out_ptr, &500u128.to_le_bytes());
  493. Ok(())
  494. }
  495. #[seal(1)]
  496. fn instantiate(
  497. code_hash_ptr: u32,
  498. _gas: u64,
  499. value_ptr: u32,
  500. input_data_ptr: u32,
  501. input_data_len: u32,
  502. address_ptr: u32,
  503. address_len_ptr: u32,
  504. output_ptr: u32,
  505. output_len_ptr: u32,
  506. salt_ptr: u32,
  507. salt_len: u32,
  508. ) -> Result<u32, Trap> {
  509. let code_hash = read_hash(mem, code_hash_ptr);
  510. let salt = read_buf(mem, salt_ptr, salt_len);
  511. let input = read_buf(mem, input_data_ptr, input_data_len);
  512. let value = read_value(mem, value_ptr);
  513. if value > vm.accounts[vm.account].value {
  514. return Ok(5); // ReturnCode::TransferFailed
  515. }
  516. let ((flags, data), state) = match vm.deploy(code_hash, value, &salt, input) {
  517. Some(Ok(state)) => ((state.data().output.as_data()), state),
  518. Some(Err(_)) => return Ok(1), // ReturnCode::CalleeTrapped
  519. None => return Ok(7), // ReturnCode::CodeNotFound
  520. };
  521. if output_len_ptr != u32::MAX {
  522. write_buf(mem, output_ptr, &data);
  523. write_buf(mem, output_len_ptr, &(data.len() as u32).to_le_bytes());
  524. }
  525. let address = state.data().accounts.last().unwrap().address;
  526. write_buf(mem, address_ptr, &address);
  527. write_buf(mem, address_len_ptr, &(address.len() as u32).to_le_bytes());
  528. if flags == 0 {
  529. vm.accept_state(state.into_data(), value);
  530. return Ok(0);
  531. }
  532. Ok(2) // Callee reverted
  533. }
  534. #[seal(0)]
  535. fn transfer(
  536. account_ptr: u32,
  537. account_len: u32,
  538. value_ptr: u32,
  539. value_len: u32,
  540. ) -> Result<u32, Trap> {
  541. assert_eq!(account_len, 32);
  542. assert_eq!(value_len, 16);
  543. let value = read_value(mem, value_ptr);
  544. if value > vm.accounts[vm.account].value {
  545. return Ok(5); // ReturnCode::TransferFailed
  546. }
  547. let account = read_account(mem, account_ptr);
  548. if let Some(to) = vm.accounts.iter_mut().find(|c| c.address == account) {
  549. to.value += value;
  550. vm.accounts[vm.account].value -= value;
  551. return Ok(0);
  552. }
  553. Ok(5)
  554. }
  555. #[seal(0)]
  556. fn address(out_ptr: u32, out_len_ptr: u32) -> Result<(), Trap> {
  557. let address = vm.accounts[vm.account].address;
  558. let out_len = read_len(mem, out_len_ptr);
  559. assert!(out_len >= address.len());
  560. write_buf(mem, out_ptr, &address);
  561. write_buf(mem, out_len_ptr, &(address.len() as u32).to_le_bytes());
  562. Ok(())
  563. }
  564. #[seal(0)]
  565. fn caller(out_ptr: u32, out_len_ptr: u32) -> Result<(), Trap> {
  566. let out_len = read_len(mem, out_len_ptr);
  567. let address = vm.accounts[vm.caller_account].address;
  568. assert!(out_len >= address.len());
  569. write_buf(mem, out_ptr, &address);
  570. write_buf(mem, out_len_ptr, &(address.len() as u32).to_le_bytes());
  571. Ok(())
  572. }
  573. #[seal(0)]
  574. fn balance(out_ptr: u32, out_len_ptr: u32) -> Result<(), Trap> {
  575. let balance = vm.accounts[vm.account].value.to_le_bytes();
  576. let out_len = read_len(mem, out_len_ptr);
  577. assert!(out_len >= balance.len());
  578. write_buf(mem, out_ptr, &balance);
  579. write_buf(mem, out_len_ptr, &(balance.len() as u32).to_le_bytes());
  580. Ok(())
  581. }
  582. #[seal(0)]
  583. fn block_number(out_ptr: u32, out_len_ptr: u32) -> Result<(), Trap> {
  584. let block = 950_119_597u32.to_le_bytes();
  585. let out_len = read_len(mem, out_len_ptr);
  586. assert!(out_len >= block.len());
  587. write_buf(mem, out_ptr, &block);
  588. write_buf(mem, out_len_ptr, &(block.len() as u32).to_le_bytes());
  589. Ok(())
  590. }
  591. #[seal(0)]
  592. fn now(out_ptr: u32, out_len_ptr: u32) -> Result<(), Trap> {
  593. let now = 1594035638000u64.to_le_bytes();
  594. let out_len = read_len(mem, out_len_ptr);
  595. assert!(out_len >= now.len());
  596. write_buf(mem, out_ptr, &now);
  597. write_buf(mem, out_len_ptr, &(now.len() as u32).to_le_bytes());
  598. Ok(())
  599. }
  600. #[seal(0)]
  601. fn gas_left(out_ptr: u32, out_len_ptr: u32) -> Result<(), Trap> {
  602. let gas = 2_224_097_461u64.to_le_bytes();
  603. let out_len = read_len(mem, out_len_ptr);
  604. assert!(out_len >= gas.len());
  605. write_buf(mem, out_ptr, &gas);
  606. write_buf(mem, out_len_ptr, &(gas.len() as u32).to_le_bytes());
  607. Ok(())
  608. }
  609. #[seal(0)]
  610. fn weight_to_fee(gas: u64, out_ptr: u32, out_len_ptr: u32) -> Result<(), Trap> {
  611. let price = (59_541_253_813_967 * gas as u128).to_le_bytes();
  612. let out_len = read_len(mem, out_len_ptr);
  613. assert!(out_len >= price.len());
  614. write_buf(mem, out_ptr, &price);
  615. write_buf(mem, out_len_ptr, &(price.len() as u32).to_le_bytes());
  616. Ok(())
  617. }
  618. #[seal(1)]
  619. fn terminate(beneficiary_ptr: u32) -> Result<(), Trap> {
  620. let free = vm.accounts.remove(vm.account).value;
  621. let address = read_account(mem, beneficiary_ptr);
  622. println!("seal_terminate: {} gets {free}", hex::encode(address));
  623. if let Some(to) = vm.accounts.iter_mut().find(|a| a.address == address) {
  624. to.value += free;
  625. }
  626. Err(HostReturn::Terminate.into())
  627. }
  628. #[seal(0)]
  629. fn deposit_event(
  630. topics_ptr: u32,
  631. topics_len: u32,
  632. data_ptr: u32,
  633. data_len: u32,
  634. ) -> Result<(), Trap> {
  635. let data = read_buf(mem, data_ptr, data_len);
  636. let topics = if topics_len > 0 {
  637. <Vec<Hash>>::decode(&mut &read_buf(mem, topics_ptr, topics_len)[..]).unwrap()
  638. } else {
  639. vec![]
  640. };
  641. println!(
  642. "seal_deposit_event data: {} topics: {:?}",
  643. hex::encode(&data),
  644. topics.iter().map(hex::encode).collect::<Vec<_>>()
  645. );
  646. vm.events.push(Event { data, topics });
  647. Ok(())
  648. }
  649. /// Mock chain extension with ID 123 that writes the reversed input to the output buf.
  650. /// Returns the sum of the input data.
  651. #[seal(0)]
  652. fn call_chain_extension(
  653. id: u32,
  654. input_ptr: u32,
  655. input_len: u32,
  656. output_ptr: u32,
  657. output_len_ptr: u32,
  658. ) -> Result<u32, Trap> {
  659. assert_eq!(id, 123, "unknown chain extension");
  660. assert!(read_len(mem, output_len_ptr) == 16384 && input_len <= 16384);
  661. let mut data = read_buf(mem, input_ptr, input_len);
  662. data.reverse();
  663. write_buf(mem, output_ptr, &data);
  664. write_buf(mem, output_len_ptr, &(data.len() as u32).to_le_bytes());
  665. Ok(data.iter().map(|i| *i as u32).sum())
  666. }
  667. #[seal(0)]
  668. fn is_contract(input_ptr: u32) -> Result<u32, Trap> {
  669. let address = read_account(mem, input_ptr);
  670. Ok(vm
  671. .accounts
  672. .iter()
  673. .any(|account| account.contract.is_some() && account.address == address)
  674. .into())
  675. }
  676. #[seal(0)]
  677. fn caller_is_root() -> Result<u32, Trap> {
  678. Ok((vm.accounts[vm.caller_account].address == [0; 32]).into())
  679. }
  680. #[seal(0)]
  681. fn set_code_hash(code_hash_ptr: u32) -> Result<u32, Trap> {
  682. let hash = read_hash(mem, code_hash_ptr);
  683. if let Some(code) = vm.blobs.iter().find(|code| code.hash == hash) {
  684. vm.accounts[vm.account].contract.as_mut().unwrap().code = code.clone();
  685. return Ok(0);
  686. }
  687. Ok(7) // ReturnCode::CodeNoteFound
  688. }
  689. }
  690. /// Provides a mock implementation of substrates [contracts pallet][1]
  691. ///
  692. /// [1]: https://docs.rs/pallet-contracts/latest/pallet_contracts/index.html
  693. pub struct MockSubstrate(Store<Runtime>);
  694. impl MockSubstrate {
  695. fn invoke(&mut self, export: &str, input: Vec<u8>) -> Result<(), Error> {
  696. let callee = self.0.data().account;
  697. let value = self.0.data().transferred_value;
  698. let runtime = self.0.data_mut();
  699. runtime.debug_buffer.clear();
  700. runtime.events.clear();
  701. runtime.called_accounts.clear();
  702. self.0 = runtime.call(export, callee, input, value).unwrap()?;
  703. self.0.data_mut().transferred_value = 0;
  704. Ok(())
  705. }
  706. /// Overwrites the address at associated `account` index with the given `address`.
  707. pub fn set_account_address(&mut self, account: usize, address: [u8; 32]) {
  708. self.0.data_mut().accounts[account].address = address;
  709. }
  710. /// Specify the caller account index for the next function or constructor call.
  711. pub fn set_account(&mut self, index: usize) {
  712. self.0.data_mut().account = index;
  713. }
  714. /// Specify the balance for the next function or constructor call.
  715. pub fn set_transferred_value(&mut self, amount: u128) {
  716. self.0.data_mut().transferred_value = amount;
  717. }
  718. /// Get the balance of the given `account`.
  719. pub fn balance(&self, account: usize) -> u128 {
  720. self.0.data().accounts[account].value
  721. }
  722. /// Get the address of the calling account.
  723. pub fn caller(&self) -> Address {
  724. self.0.data().accounts[self.0.data().caller_account].address
  725. }
  726. /// Get the output of the last function or constructor call.
  727. pub fn output(&self) -> Vec<u8> {
  728. if let HostReturn::Data(_, data) = &self.0.data().output {
  729. return data.to_vec();
  730. }
  731. vec![]
  732. }
  733. /// Get the debug buffer contents of the last function or constructor call.
  734. pub fn debug_buffer(&self) -> String {
  735. self.0.data().debug_buffer.clone()
  736. }
  737. /// Get the emitted events of the last function or constructor call.
  738. pub fn events(&self) -> Vec<Event> {
  739. self.0.data().events.clone()
  740. }
  741. /// Get a list of all deployed contracts.
  742. pub fn contracts(&self) -> Vec<&Contract> {
  743. self.0
  744. .data()
  745. .accounts
  746. .iter()
  747. .map(|a| a.contract.as_ref().unwrap())
  748. .collect()
  749. }
  750. /// Read the storage of the account that was (or is about to be) called.
  751. pub fn storage(&self) -> &HashMap<StorageKey, Vec<u8>> {
  752. &self.0.data().accounts[self.0.data().account]
  753. .contract
  754. .as_ref()
  755. .unwrap()
  756. .storage
  757. }
  758. /// Get the selector of the given `function_name` on the given `contract` index.
  759. pub fn selector(&self, contract: usize, function_name: &str) -> &[u8] {
  760. &self.0.data().blobs[contract].messages[function_name]
  761. }
  762. /// Execute the constructor `index` with the given input `args`.
  763. pub fn constructor(&mut self, index: usize, mut args: Vec<u8>) {
  764. let mut input = self.0.data().blobs[self.0.data().account].constructors[index].clone();
  765. input.append(&mut args);
  766. self.raw_constructor(input);
  767. }
  768. /// Get a list of all uploaded contracts
  769. pub fn blobs(&self) -> Vec<WasmCode> {
  770. self.0.data().blobs.clone()
  771. }
  772. /// Call the "deploy" function with the given `input`.
  773. ///
  774. /// `input` must contain the selector fo the constructor.
  775. pub fn raw_constructor(&mut self, input: Vec<u8>) {
  776. self.invoke("deploy", input).unwrap();
  777. if let HostReturn::Data(flags, _) = self.0.data().output {
  778. assert!(flags == 0)
  779. }
  780. }
  781. /// Call the contract function `name` with the given input `args`.
  782. /// Panics if the contract traps or reverts.
  783. pub fn function(&mut self, name: &str, mut args: Vec<u8>) {
  784. let mut input = self.0.data().blobs[self.0.data().account].messages[name].clone();
  785. input.append(&mut args);
  786. self.raw_function(input);
  787. }
  788. /// Expect the contract function `name` with the given input `args` to trap or revert.
  789. ///
  790. /// Only traps caused by an `unreachable` instruction are allowed. Other traps will panic instead.
  791. pub fn function_expect_failure(&mut self, name: &str, mut args: Vec<u8>) {
  792. let mut input = self.0.data().blobs[self.0.data().account].messages[name].clone();
  793. input.append(&mut args);
  794. self.raw_function_failure(input);
  795. }
  796. /// Call the "deploy" function with the given `input`.
  797. ///
  798. /// `input` must contain the selector fo the constructor.
  799. pub fn raw_function(&mut self, input: Vec<u8>) {
  800. self.invoke("call", input).unwrap();
  801. if let HostReturn::Data(flags, _) = self.0.data().output {
  802. assert!(flags == 0)
  803. }
  804. }
  805. fn raw_failure(&mut self, export: &str, input: Vec<u8>) {
  806. match self.invoke(export, input) {
  807. Err(wasmi::Error::Trap(trap)) => match trap.trap_code() {
  808. Some(TrapCode::UnreachableCodeReached) => (),
  809. _ => panic!("trap: {trap:?}"),
  810. },
  811. Err(err) => panic!("unexpected error: {err:?}"),
  812. Ok(_) => match self.0.data().output {
  813. HostReturn::Data(1, _) => (),
  814. _ => panic!("unexpected return from main"),
  815. },
  816. }
  817. }
  818. /// Call the "call" function with the given input and expect the contract to trap.
  819. ///
  820. /// `input` must contain the desired function selector.
  821. ///
  822. /// Only traps caused by an `unreachable` instruction are allowed. Other traps will panic instead.
  823. pub fn raw_function_failure(&mut self, input: Vec<u8>) {
  824. self.raw_failure("call", input);
  825. }
  826. /// Call the "deploy" function with the given input and expect the contract to trap.
  827. ///
  828. /// `input` must contain the desired function selector.
  829. ///
  830. /// Only traps caused by an `unreachable` instruction are allowed. Other traps will panic instead.
  831. pub fn raw_constructor_failure(&mut self, input: Vec<u8>) {
  832. self.raw_failure("deploy", input);
  833. }
  834. pub fn heap_verify(&mut self) {
  835. let mem = self.0.data().memory.unwrap().data(&mut self.0);
  836. let memsize = mem.len();
  837. println!("memory size:{memsize}");
  838. let mut current_elem = 0x10000;
  839. let mut last_elem = 0u32;
  840. let read_u32 = |ptr| u32::from_le_bytes(mem[ptr..ptr + 4].try_into().unwrap());
  841. loop {
  842. let next: u32 = read_u32(current_elem);
  843. let prev: u32 = read_u32(current_elem + 4);
  844. let length: u32 = read_u32(current_elem + 8);
  845. let allocated: u32 = read_u32(current_elem + 12);
  846. println!("next:{next:08x} prev:{prev:08x} length:{length} allocated:{allocated}");
  847. let buf = read_buf(mem, current_elem as u32 + 16, length);
  848. if allocated == 0 {
  849. println!("{:08x} {} not allocated", current_elem + 16, length);
  850. } else {
  851. println!("{:08x} {} allocated", current_elem + 16, length);
  852. assert_eq!(allocated & 0xffff, 1);
  853. for offset in (0..buf.len()).step_by(16) {
  854. let mut hex = "\t".to_string();
  855. let mut chars = "\t".to_string();
  856. for i in 0..16 {
  857. if offset + i >= buf.len() {
  858. break;
  859. }
  860. let b = buf[offset + i];
  861. write!(hex, " {b:02x}").unwrap();
  862. if b.is_ascii() && !b.is_ascii_control() {
  863. write!(chars, " {}", b as char).unwrap();
  864. } else {
  865. chars.push_str(" ");
  866. }
  867. }
  868. println!("{hex}\n{chars}");
  869. }
  870. }
  871. assert_eq!(last_elem, prev);
  872. if next == 0 {
  873. break;
  874. }
  875. last_elem = current_elem as u32;
  876. current_elem = next as usize;
  877. }
  878. }
  879. }
  880. /// Build all contracts found in `src` and set up a mock runtime.
  881. ///
  882. /// The mock runtime will contain a contract account for each contract in `src`.
  883. /// Constructors are _not_ called, therefore the storage will not be initialized.
  884. pub fn build_solidity(src: &str) -> MockSubstrate {
  885. build_solidity_with_options(src, true)
  886. }
  887. /// A variant of `MockSubstrate::build_solidity()` with the ability to specify compiler options:
  888. /// * log_ret: enable logging of host function return codes
  889. /// * log_err: enable logging of runtime errors
  890. pub fn build_solidity_with_options(src: &str, log_err: bool) -> MockSubstrate {
  891. let blobs = build_wasm(src, log_err)
  892. .iter()
  893. .map(|(code, abi)| WasmCode::new(abi, code))
  894. .collect();
  895. MockSubstrate(Store::new(&Engine::default(), Runtime::new(blobs)))
  896. }
  897. pub fn build_wasm(src: &str, log_err: bool) -> Vec<(Vec<u8>, String)> {
  898. let tmp_file = OsStr::new("test.sol");
  899. let mut cache = FileResolver::default();
  900. cache.set_file_contents(tmp_file.to_str().unwrap(), src.to_string());
  901. let opt = inkwell::OptimizationLevel::Default;
  902. let target = Target::default_polkadot();
  903. let (wasm, ns) = compile(
  904. tmp_file,
  905. &mut cache,
  906. target,
  907. &Options {
  908. opt_level: opt.into(),
  909. log_runtime_errors: log_err,
  910. log_prints: true,
  911. #[cfg(feature = "wasm_opt")]
  912. wasm_opt: Some(contract_build::OptimizationPasses::Z),
  913. ..Default::default()
  914. },
  915. vec!["unknown".to_string()],
  916. "0.0.1",
  917. );
  918. ns.print_diagnostics_in_plain(&cache, false);
  919. assert!(!wasm.is_empty());
  920. wasm
  921. }
  922. pub fn load_abi(s: &str) -> InkProject {
  923. let bundle = serde_json::from_str::<ContractMetadata>(s).unwrap();
  924. serde_json::from_value::<InkProject>(serde_json::to_value(bundle.abi).unwrap()).unwrap()
  925. }