--- a/Cargo.lock +++ b/Cargo.lock @@ -5871,7 +5871,7 @@ [[package]] name = "pallet-evm-coder-substrate" -version = "0.1.1" +version = "0.1.2" dependencies = [ "ethereum", "evm-coder", --- /dev/null +++ b/pallets/evm-coder-substrate/CHANGELOG.md @@ -0,0 +1,12 @@ +# Change Log + +All notable changes to this project will be documented in this file. + +## [0.1.2] - 2022-08-12 + +### Fixed + + - Issue with error not being thrown when non existing function is called on collection contract + + + \ No newline at end of file --- a/pallets/evm-coder-substrate/Cargo.toml +++ b/pallets/evm-coder-substrate/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-evm-coder-substrate" -version = "0.1.1" +version = "0.1.2" license = "GPLv3" edition = "2021" --- a/pallets/evm-coder-substrate/src/lib.rs +++ b/pallets/evm-coder-substrate/src/lib.rs @@ -261,7 +261,8 @@ let (selector, mut reader) = AbiReader::new_call(input)?; let call = C::parse(selector, &mut reader)?; if call.is_none() { - return Ok(None); + let selector = u32::from_be_bytes(selector); + return Err(format!("unrecognized selector: 0x{selector:0<8x}").into()); } let call = call.unwrap(); --- /dev/null +++ b/tests/src/evmCoder.test.ts @@ -0,0 +1,117 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +import Web3 from 'web3'; +import {createEthAccountWithBalance, createRefungibleCollection, GAS_ARGS, itWeb3} from './eth/util/helpers'; +import * as solc from 'solc'; + +import chai from 'chai'; +const expect = chai.expect; + +async function compileTestContract(collectionAddress: string, contractAddress: string) { + const input = { + language: 'Solidity', + sources: { + ['Test.sol']: { + content: + ` + // SPDX-License-Identifier: MIT + pragma solidity ^0.8.0; + interface ITest { + function ztestzzzzzzz() external returns (uint256 n); + } + contract Test { + event Result(bool, uint256); + function test1() public { + try + ITest(${collectionAddress}).ztestzzzzzzz() + returns (uint256 n) { + // enters + emit Result(true, n); // => [true, BigNumber { value: "43648854190028290368124427828690944273759144372138548774646036134290060795932" }] + } catch { + emit Result(false, 0); + } + } + function test2() public { + try + ITest(${contractAddress}).ztestzzzzzzz() + returns (uint256 n) { + emit Result(true, n); + } catch { + // enters + emit Result(false, 0); // => [ false, BigNumber { value: "0" } ] + } + } + function test3() public { + ITest(${collectionAddress}).ztestzzzzzzz(); + } + } + `, + }, + }, + settings: { + outputSelection: { + '*': { + '*': ['*'], + }, + }, + }, + }; + const json = JSON.parse(solc.compile(JSON.stringify(input))); + const out = json.contracts['Test.sol']['Test']; + + return { + abi: out.abi, + object: '0x' + out.evm.bytecode.object, + }; +} + +async function deployTestContract(web3: Web3, owner: string, collectionAddress: string, contractAddress: string) { + const compiled = await compileTestContract(collectionAddress, contractAddress); + const fractionalizerContract = new web3.eth.Contract(compiled.abi, undefined, { + data: compiled.object, + from: owner, + ...GAS_ARGS, + }); + return await fractionalizerContract.deploy({data: compiled.object}).send({from: owner}); +} + +describe('Evm Coder tests', () => { + itWeb3('Call non-existing function', async ({api, web3, privateKeyWrapper}) => { + const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); + const {collectionIdAddress} = await createRefungibleCollection(api, web3, owner); + const contract = await deployTestContract(web3, owner, collectionIdAddress, '0x1bfed5D614b886b9Ab2eA4CBAc22A96B7EC29c9c'); + const testContract = await deployTestContract(web3, owner, collectionIdAddress, contract.options.address); + { + const result = await testContract.methods.test1().send(); + expect(result.events.Result.returnValues).to.deep.equal({ + '0': false, + '1': '0', + }); + } + { + const result = await testContract.methods.test2().send(); + expect(result.events.Result.returnValues).to.deep.equal({ + '0': false, + '1': '0', + }); + } + { + await expect(testContract.methods.test3().call()) + .to.be.rejectedWith(/unrecognized selector: 0xd9f02b36$/g); + } + }); +}); \ No newline at end of file