From ac099b7ee9f7fbb2dcec7a8c3c3fcb9ca796446d Mon Sep 17 00:00:00 2001 From: Stefan Stefanov Date: Tue, 17 Oct 2023 16:57:41 +0300 Subject: [PATCH 1/3] Adding tests for Arithmetic Signed-off-by: Stefan Stefanov --- contracts/solidity/cryptomath/Arithmetic.sol | 78 +++++++++++++ test/constants.js | 1 + test/solidity/cryptomath/arithmetic.js | 110 +++++++++++++++++++ 3 files changed, 189 insertions(+) create mode 100644 contracts/solidity/cryptomath/Arithmetic.sol create mode 100644 test/solidity/cryptomath/arithmetic.js diff --git a/contracts/solidity/cryptomath/Arithmetic.sol b/contracts/solidity/cryptomath/Arithmetic.sol new file mode 100644 index 000000000..ba92ec741 --- /dev/null +++ b/contracts/solidity/cryptomath/Arithmetic.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +contract Arithmetic { + string public name = "Arithmetic"; + uint256 maxUint = type(uint256).max; + uint256 minUint = type(uint256).min; + + function checkName() external view returns (string memory){ + return name; + } + + function add() external returns (bool) { + name = "Arithmetic check if NOT reverted"; + maxUint = maxUint + 1; + return true; + } + + function add2() external returns (uint) { + uint256 tmp = maxUint; + name = "Arithmetic check if NOT reverted"; + tmp += 100; + + return tmp; + } + + function mul() external returns (bool) { + uint8 maxUint8 = type(uint8).max; + name = "Arithmetic check if NOT reverted"; + maxUint8 * 2; + + return true; + } + + function dec() external returns (bool) { + // This subtraction will revert on underflow. + name = "Arithmetic check if NOT reverted"; + minUint--; + + return true; + } + + function sub() external returns (bool) { + uint256 tmp = minUint; + name = "Arithmetic check if NOT reverted"; + tmp -= 1; + + return true; + } + + function negativeHasMoreValues() external returns (bool) { + int tmp; + int x = type(int).min; + name = "Arithmetic check if NOT reverted"; + tmp = -x; + + return true; + } + + function uncheckedAdd() external view returns (bool) { + unchecked { + uint256 tmp; + tmp = maxUint + 1; + + return true; + } + } + + function uncheckedSub() external view returns (bool) { + unchecked { + uint256 tmp = minUint; + tmp -= 1; + + return true; + } + } + +} diff --git a/test/constants.js b/test/constants.js index ac78e8e25..0380eabfb 100644 --- a/test/constants.js +++ b/test/constants.js @@ -112,6 +112,7 @@ const Contract = { FunctionsChild: 'FunctionsChild', FunctionsParent: 'FunctionsParent', Scoping: 'Scoping', + Arithmetic: "Arithmetic" } const CALL_EXCEPTION = 'CALL_EXCEPTION' diff --git a/test/solidity/cryptomath/arithmetic.js b/test/solidity/cryptomath/arithmetic.js new file mode 100644 index 000000000..c1eede79d --- /dev/null +++ b/test/solidity/cryptomath/arithmetic.js @@ -0,0 +1,110 @@ +/*- + * + * Hedera Smart Contracts + * + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +const { expect } = require('chai') +const { ethers } = require('hardhat') +const Constants = require('../../constants') + +describe('Arithmetic Test Suite', function () { + let contract, signers; + + before(async function () { + signers = await ethers.getSigners() + + const factory = await ethers.getContractFactory(Constants.Contract.Arithmetic) + contract = await factory.deploy() + }); + + it('it should confirm solidity functionality: Arithmetic, checked overflow - confirm revert add', async function () { + try { + const res = await contract.add() + await res.wait() + } catch (error) { + expect(error).to.exist + const name = await contract.checkName() + expect(name).to.equal('Arithmetic') + } + }); + + it('it should confirm solidity functionality: Arithmetic, checked overflow - confirm revert add2', async function () { + try { + const res = await contract.add2() + await res.wait() + } catch (error) { + expect(error).to.exist + const name = await contract.checkName() + expect(name).to.equal('Arithmetic') + } + }); + + it('it should confirm solidity functionality: Arithmetic, checked overflow - confirm revert mul', async function () { + try { + const res = await contract.mul() + await res.wait() + } catch (error) { + expect(error).to.exist + const name = await contract.checkName() + expect(name).to.equal('Arithmetic') + } + }); + + it('it should confirm solidity functionality: Arithmetic, checked underflow - confirm revert sub', async function () { + try { + const res = await contract.sub() + await res.wait() + } catch (error) { + expect(error).to.exist + const name = await contract.checkName() + expect(name).to.equal('Arithmetic') + } + }); + + it('it should confirm solidity functionality: Arithmetic, checked underflow - confirm revert dec', async function () { + try { + const res = await contract.dec() + await res.wait() + } catch (error) { + expect(error).to.exist + const name = await contract.checkName() + expect(name).to.equal('Arithmetic') + } + }); + + it('it should confirm solidity functionality: Arithmetic, checked underflow - confirm revert negativeHasMoreValues', async function () { + try { + const res = await contract.negativeHasMoreValues() + await res.wait() + } catch (error) { + expect(error).to.exist + const name = await contract.checkName() + expect(name).to.equal('Arithmetic') + } + }); + + it('it should confirm solidity functionality: Arithmetic, unchecked overflow - confirm wrap uncheckedAdd', async function () { + const res = await contract.uncheckedAdd() + expect(res).to.be.true + }); + + it('it should confirm solidity functionality: Arithmetic, unchecked underflow - confirm wrap uncheckedSub', async function () { + const res = await contract.uncheckedSub() + expect(res).to.be.true + }); + +}) From feac540f2d1a5190f7d5e866e09dae462a9d5613 Mon Sep 17 00:00:00 2001 From: Stefan Stefanov Date: Wed, 18 Oct 2023 11:07:42 +0300 Subject: [PATCH 2/3] Addressing comments Signed-off-by: Stefan Stefanov --- contracts/solidity/cryptomath/Arithmetic.sol | 23 +++++--------------- test/solidity/cryptomath/arithmetic.js | 22 ++++++++++++++++--- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/contracts/solidity/cryptomath/Arithmetic.sol b/contracts/solidity/cryptomath/Arithmetic.sol index ba92ec741..a348b1cea 100644 --- a/contracts/solidity/cryptomath/Arithmetic.sol +++ b/contracts/solidity/cryptomath/Arithmetic.sol @@ -10,51 +10,40 @@ contract Arithmetic { return name; } - function add() external returns (bool) { + function add() external { name = "Arithmetic check if NOT reverted"; maxUint = maxUint + 1; - return true; } - function add2() external returns (uint) { + function add2() external { uint256 tmp = maxUint; name = "Arithmetic check if NOT reverted"; tmp += 100; - - return tmp; } - function mul() external returns (bool) { + function mul() external { uint8 maxUint8 = type(uint8).max; name = "Arithmetic check if NOT reverted"; maxUint8 * 2; - - return true; } - function dec() external returns (bool) { + function dec() external { // This subtraction will revert on underflow. name = "Arithmetic check if NOT reverted"; minUint--; - - return true; } - function sub() external returns (bool) { + function sub() external { uint256 tmp = minUint; name = "Arithmetic check if NOT reverted"; tmp -= 1; - - return true; } - function negativeHasMoreValues() external returns (bool) { + function negativeHasMoreValues() external { int tmp; int x = type(int).min; name = "Arithmetic check if NOT reverted"; tmp = -x; - - return true; } function uncheckedAdd() external view returns (bool) { diff --git a/test/solidity/cryptomath/arithmetic.js b/test/solidity/cryptomath/arithmetic.js index c1eede79d..2f0f0c43b 100644 --- a/test/solidity/cryptomath/arithmetic.js +++ b/test/solidity/cryptomath/arithmetic.js @@ -22,79 +22,95 @@ const { ethers } = require('hardhat') const Constants = require('../../constants') describe('Arithmetic Test Suite', function () { - let contract, signers; + let contract; before(async function () { - signers = await ethers.getSigners() - const factory = await ethers.getContractFactory(Constants.Contract.Arithmetic) contract = await factory.deploy() }); it('it should confirm solidity functionality: Arithmetic, checked overflow - confirm revert add', async function () { + let hasError = false; try { const res = await contract.add() await res.wait() } catch (error) { + hasError = true; expect(error).to.exist const name = await contract.checkName() expect(name).to.equal('Arithmetic') } + expect(hasError).to.be.true; }); it('it should confirm solidity functionality: Arithmetic, checked overflow - confirm revert add2', async function () { + let hasError = false; try { const res = await contract.add2() await res.wait() } catch (error) { + hasError = true; expect(error).to.exist const name = await contract.checkName() expect(name).to.equal('Arithmetic') } + expect(hasError).to.be.true; }); it('it should confirm solidity functionality: Arithmetic, checked overflow - confirm revert mul', async function () { + let hasError = false; try { const res = await contract.mul() await res.wait() } catch (error) { + hasError = true; expect(error).to.exist const name = await contract.checkName() expect(name).to.equal('Arithmetic') } + expect(hasError).to.be.true; }); it('it should confirm solidity functionality: Arithmetic, checked underflow - confirm revert sub', async function () { + let hasError = false; try { const res = await contract.sub() await res.wait() } catch (error) { + hasError = true; expect(error).to.exist const name = await contract.checkName() expect(name).to.equal('Arithmetic') } + expect(hasError).to.be.true; }); it('it should confirm solidity functionality: Arithmetic, checked underflow - confirm revert dec', async function () { + let hasError = false; try { const res = await contract.dec() await res.wait() } catch (error) { + hasError = true; expect(error).to.exist const name = await contract.checkName() expect(name).to.equal('Arithmetic') } + expect(hasError).to.be.true; }); it('it should confirm solidity functionality: Arithmetic, checked underflow - confirm revert negativeHasMoreValues', async function () { + let hasError = false; try { const res = await contract.negativeHasMoreValues() await res.wait() } catch (error) { + hasError = true; expect(error).to.exist const name = await contract.checkName() expect(name).to.equal('Arithmetic') } + expect(hasError).to.be.true; }); it('it should confirm solidity functionality: Arithmetic, unchecked overflow - confirm wrap uncheckedAdd', async function () { From e867e2d6c46f4ca081c3995db85148e9d99ac5a8 Mon Sep 17 00:00:00 2001 From: Stefan Stefanov Date: Thu, 19 Oct 2023 19:48:28 +0300 Subject: [PATCH 3/3] Fixing test errors Signed-off-by: Stefan Stefanov --- test/solidity/cryptomath/CryptoMath.js | 1 - utils/helpers.js | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/test/solidity/cryptomath/CryptoMath.js b/test/solidity/cryptomath/CryptoMath.js index a94c304b8..0c4b5df43 100644 --- a/test/solidity/cryptomath/CryptoMath.js +++ b/test/solidity/cryptomath/CryptoMath.js @@ -24,7 +24,6 @@ const Constants = require('../../constants') describe('@solidityevmequiv1 CryptoMath Test Suite', function () { let cryptoMathContract, provider, signers; - before(async function () { signers = await ethers.getSigners(); provider = ethers.getDefaultProvider(); diff --git a/utils/helpers.js b/utils/helpers.js index 17eb5254d..b334af79f 100644 --- a/utils/helpers.js +++ b/utils/helpers.js @@ -102,7 +102,7 @@ const pollForNewERC721Owner = async(erc721Contract, tokenId, ownerBefore) => { return ownerAfter; // Ownership changed } - delay(); + await delay(); } throw new Error(`Ownership did not change after ${process.env.MAX_RETRY} tries`); @@ -132,7 +132,7 @@ const pollForNewERC721HollowWalletOwner = async(erc721Contract, nftTokenAddress, return ownerAfter; // Ownership changed } - delay(); + await delay(); } throw new Error(`Ownership did not change after ${process.env.MAX_RETRY} tries`); @@ -162,7 +162,7 @@ const pollForNewHollowWalletBalance = async (provider, walletAddress, balanceBef return balanceAfter; // Balance changed } - delay(); + await delay(); } throw new Error(`Failed to get a different balance value after ${process.env.MAX_RETRY} tries`);