diff --git a/contracts/yul/bitwise-coverage/Bitwise.sol b/contracts/yul/bitwise-coverage/Bitwise.sol new file mode 100644 index 000000000..9b3bb663e --- /dev/null +++ b/contracts/yul/bitwise-coverage/Bitwise.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +contract Bitwise { + /// bitwise “not” of x (every bit of x is negated) + /// example x = 2 => not(x) = -3 + /// explanation: x = 2 => binaryX = 0|0010 => ~binaryX = 1|1101 + /// 1's complement (flip bit) 1sX = 1|0010 + /// 2's complement (add 1) 2sX = 1|0010 + 1 = 1|0011 => -3 + function not(int256 x) external pure returns (int256 result) { + assembly { + result := not(x) + } + } + + /// bitwise “and” of x and y + function and(int256 x, int256 y) external pure returns (int256 result) { + assembly { + result := and(x, y) + } + } + + /// bitwise or” of x and y + function or(int256 x, int256 y) external pure returns (int256 result) { + assembly { + result := or(x, y) + } + } + + /// bitwise “xor” of x and y + function xor(int256 x, int256 y) external pure returns (int256 result) { + assembly { + result := xor(x, y) + } + } + + /// nth byte of x, where the most significant byte is the 0th byte + function extractbyteat(uint256 n, uint256 x) external pure returns (uint256 result) { + assembly { + result := byte(n , x) + } + } + + /// logical shift left y by x bits + function shl(int256 x, int256 y) external pure returns (int256 result) { + assembly { + result := shl(x, y) + } + } + + /// logical shift right y by x bits + function shr(uint256 x, uint256 y) external pure returns (uint256 result) { + assembly { + result := shr(x, y) + } + } + + /// signed arithmetic shift right y by x bits + function sar(int256 x, int256 y) external pure returns (int256 result) { + assembly { + result := sar(x, y) + } + } +} + diff --git a/test/yul/bitwise-coverage/Bitwise.js b/test/yul/bitwise-coverage/Bitwise.js new file mode 100644 index 000000000..8032d5884 --- /dev/null +++ b/test/yul/bitwise-coverage/Bitwise.js @@ -0,0 +1,80 @@ +/*- + * + * 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 Bitwise Tests', () => { + let bitwiseContract + const X = 1 + const Y = 12 + + before(async () => { + const bitwiseContractFactory = await ethers.getContractFactory('Bitwise') + bitwiseContract = await bitwiseContractFactory.deploy() + }) + + it('Should execute not(x)', async () => { + const result = await bitwiseContract.not(Y) + expect(result).to.eq(~Y) + }) + + it('Should execute and(x, y)', async () => { + const result = await bitwiseContract.and(X, Y) + expect(result).to.eq(X & Y) + }) + + it('Should execute or(x, y)', async () => { + const result = await bitwiseContract.or(X, Y) + expect(result).to.eq(X | Y) + }) + + it('Should execute xor(x, y)', async () => { + const result = await bitwiseContract.xor(X, Y) + expect(result).to.eq(X ^ Y) + }) + + it('Should execute extractbyteat(n, x)', async () => { + const DATA = 0x01020304 + const N = 31 // 32nd byte - since `DATA` is supposed to be a 256-bit (32 bytes) unsigned integer, Solidity will convert the `DATA` to bytes32 by padding 0s in front of the actual data + const EXPECTED_RESULT = 4 // last byte + + const result = await bitwiseContract.extractbyteat(N, DATA) + + expect(result).to.eq(EXPECTED_RESULT) + }) + + it('Should execute shl(x, y)', async () => { + const result = await bitwiseContract.shl(X, Y) + expect(result).to.eq(Y << X) + }) + + it('Should execute shr(x, y)', async () => { + const result = await bitwiseContract.shr(X, Y) + expect(result).to.eq(Y >> X) + }) + + it('Should execute sar(x, y)', async () => { + const SX = -3 + const SY = -9 + const result = await bitwiseContract.sar(SX, SY) + expect(result).to.eq(SY >> SX) + }) +})