From e7dd7b720064f5f7651e4d87e8c1a29a2c2f605a Mon Sep 17 00:00:00 2001 From: Logan Nguyen Date: Wed, 25 Oct 2023 22:38:53 -0500 Subject: [PATCH] feat: added math coverage solidity example contract (#511) (#521) * feat: added yul math coverage solidity example contract (#511) Signed-off-by: Logan Nguyen * update: added empty line Signed-off-by: Logan Nguyen --------- Signed-off-by: Logan Nguyen --- contracts/yul/math-coverage/MatchCoverage.sol | 118 +++++++++++++++ test/yul/math-coverage/MathCoverage.js | 141 ++++++++++++++++++ 2 files changed, 259 insertions(+) create mode 100644 contracts/yul/math-coverage/MatchCoverage.sol create mode 100644 test/yul/math-coverage/MathCoverage.js diff --git a/contracts/yul/math-coverage/MatchCoverage.sol b/contracts/yul/math-coverage/MatchCoverage.sol new file mode 100644 index 000000000..8c661e7c2 --- /dev/null +++ b/contracts/yul/math-coverage/MatchCoverage.sol @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +contract MathCoverage { + + /// addition + function add(int256 x, int256 y) external pure returns (int256 result){ + assembly { + result := add(x, y) + } + } + + /// subtraction + function sub(int256 x, int256 y) external pure returns (int256 result) { + assembly { + result := sub(x, y) + } + } + + /// multiply + function mul(int256 x, int256 y) external pure returns (int256 result) { + assembly { + result := mul(x, y) + } + } + + /// division - x / y or 0 if y == 0 + function div(uint256 x, uint256 y) external pure returns (uint256 result) { + assembly { + result := div(x, y) + } + } + + /// signed division - x / y, for signed numbers in two’s complement, 0 if y == 0 + function sdiv(int256 x, int256 y) external pure returns (int256 result) { + assembly { + result := sdiv(x, y) + } + } + + /// modulous - x % y, 0 if y == 0 + function mod(uint256 x, uint256 y) external pure returns (uint256 result) { + assembly { + result := mod(x, y) + } + } + + /// signed modulous - x % y, for signed numbers in two’s complement, 0 if y == 0 + function smod(int256 x, int256 y) external pure returns (int256 result) { + assembly { + result := smod(x, y) + } + } + + /// exponent - x to the power of y + function exp(int256 x, int256 y) external pure returns (int256 result) { + assembly { + result := exp(x, y) + } + } + + /// less than - 1 if x < y, 0 otherwise + function lt(uint256 x, uint256 y) external pure returns (uint256 result) { + assembly { + result := lt(x, y) + } + } + + /// greater than - 1 if x > y, 0 otherwise + function gt(uint256 x, uint256 y) external pure returns (uint256 result) { + assembly { + result := gt(x, y) + } + } + + /// signed less than - 1 if x < y, 0 otherwise, for signed numbers in two’s complement + function slt(int256 x, int256 y) external pure returns (int256 result) { + assembly { + result := slt(x, y) + } + } + + /// signed greater than - 1 if x > y, 0 otherwise, for signed numbers in two’s complement + function sgt(int256 x, int256 y) external pure returns (int256 result) { + assembly { + result := sgt(x, y) + } + } + + /// equal - 1 if x == y, 0 otherwise + function eq(int256 x, int256 y) external pure returns (int256 result) { + assembly { + result := eq(x, y) + } + } + + /// is zero - 1 if x == 0, 0 otherwise + function iszero(int256 x) external pure returns (int256 result) { + assembly { + result := iszero(x) + } + } + + /// add modulous - (x + y) % m with arbitrary precision arithmetic, 0 if m == 0 + function addMod(int256 x, int256 y, int256 m) external pure returns (int256 result) { + assembly { + result := addmod(x, y, m) + } + } + + /// multiply modulous - (x * y) % m with arbitrary precision arithmetic, 0 if m == 0 + function mulMod(int256 x, int256 y, int256 m) external pure returns (int256 result) { + assembly { + result := mulmod(x, y, m) + } + } +} + diff --git a/test/yul/math-coverage/MathCoverage.js b/test/yul/math-coverage/MathCoverage.js new file mode 100644 index 000000000..f2148017b --- /dev/null +++ b/test/yul/math-coverage/MathCoverage.js @@ -0,0 +1,141 @@ +/*- + * + * 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') + +describe('solidityequiv5 Math coverage tests', () => { + let mathCoverageContract + const X = 6 + const SX = -6 + const Y = 3 + const SY = -3 + const M = 2 + + before(async () => { + const mathConverageContractFactory = await ethers.getContractFactory( + 'MathCoverage' + ) + + mathCoverageContract = await mathConverageContractFactory.deploy() + }) + + it('Should execute add(x, y)', async () => { + const result = await mathCoverageContract.add(X, Y) + + expect(result).to.eq(X + Y) + }) + + it('Should execute sub(x, y)', async () => { + const result = await mathCoverageContract.sub(X, Y) + + expect(result).to.eq(X - Y) + }) + + it('Should execute mul(x, y)', async () => { + const result = await mathCoverageContract.mul(X, Y) + + expect(result).to.eq(X * Y) + }) + + it('Should execute div(x, y)', async () => { + const result = await mathCoverageContract.div(X, Y) + const zeroResult = await mathCoverageContract.div(X, 0) + + expect(result).to.eq(X / Y) + expect(zeroResult).to.eq(0) + }) + + it('Should execute sdiv(x, y)', async () => { + const result = await mathCoverageContract.sdiv(SX, SY) + const zeroResult = await mathCoverageContract.sdiv(SX, 0) + + expect(result).to.eq(SX / SY) + expect(zeroResult).to.eq(0) + }) + + it('Should execute mod(x, y)', async () => { + const result = await mathCoverageContract.mod(X, Y) + + expect(result).to.eq(X % Y) + }) + + it('Should execute smod(x, y)', async () => { + const result = await mathCoverageContract.smod(SX, SY) + + expect(result).to.eq(SX % SY) + }) + + it('Should execute exp(x, y)', async () => { + const result = await mathCoverageContract.exp(X, Y) + + expect(result).to.eq(X ** Y) + }) + + it('Should execute lt(x, y)', async () => { + const result = await mathCoverageContract.lt(X, Y) + + expect(result).to.eq(X < Y ? 1 : 0) + }) + + it('Should execute gt(x, y)', async () => { + const result = await mathCoverageContract.gt(X, Y) + + expect(result).to.eq(X > Y ? 1 : 0) + }) + + it('Should execute slt(x, y)', async () => { + const result = await mathCoverageContract.slt(SX, SY) + + expect(result).to.eq(SX < SY ? 1 : 0) + }) + + it('Should execute sgt(x, y)', async () => { + const result = await mathCoverageContract.sgt(SX, SY) + + expect(result).to.eq(SX > SY ? 1 : 0) + }) + + it('Should execute eq(x, y)', async () => { + const truthResult = await mathCoverageContract.eq(X, X) + const falsyResult = await mathCoverageContract.eq(X, Y) + + expect(truthResult).to.eq(1) + expect(falsyResult).to.eq(X === Y ? 1 : 0) + }) + + it('Should execute iszero(x, y)', async () => { + const result = await mathCoverageContract.iszero(X) + + expect(result).to.eq(result === 0 ? 1 : 0) + }) + + it('Should execute addMod(x, y)', async () => { + const result = await mathCoverageContract.addMod(X, Y, M) + + expect(result).to.eq((X + Y) % M) + }) + + it('Should execute mulMod(x, y)', async () => { + const result = await mathCoverageContract.mulMod(X, Y, M) + + expect(result).to.eq((X * Y) % M) + }) +})