Skip to content

Instantly share code, notes, and snippets.

@walteh
Last active July 12, 2022 11:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save walteh/3284e1b84a54b42bbef58d56bca968f0 to your computer and use it in GitHub Desktop.
Save walteh/3284e1b84a54b42bbef58d56bca968f0 to your computer and use it in GitHub Desktop.
gas analysis of different methods of checking sign equality of integers in solidity v8
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.15;
import "forge-std/Script.sol";
import "forge-std/Test.sol";
function checkSameSign1(int256 a, int256 b) pure returns (bool sameSign) {
uint256 sa;
uint256 sb;
assembly {
sa := sgt(a, sub(0, 1))
sb := sgt(b, sub(0, 1))
sameSign := iszero(xor(sa, sb))
}
}
function checkSameSign2(int256 a, int256 b) pure returns (bool sameSign) {
assembly {
sameSign := iszero(xor(shr(255, a), shr(255, b)))
}
}
function checkSameSign3(int256 a, int256 b) pure returns (bool sameSign) {
assembly {
sameSign := eq(shr(255, a), shr(255, b))
}
}
function checkSameSign4(int256 a, int256 b) pure returns (bool sameSign) {
assembly {
sameSign := iszero(shr(255, xor(b, a)))
}
}
function checkSameSign5(int256 a, int256 b) pure returns (bool sameSign) {
assembly {
sameSign := lt(xor(a, b), 0x8000000000000000000000000000000000000000000000000000000000000000)
}
}
function execute(int256 a, int256 b) view {
console2.log("optimizer = false");
console2.log("-----------------------------------------------");
uint256 left = gasleft();
bool t1 = checkSameSign1(a, b);
left = left - gasleft();
console2.log("iszero(xor(sa, sb)): ", left, t1);
left = gasleft();
bool t2 = checkSameSign2(a, b);
left = left - gasleft();
console2.log("iszero(xor(shr(255, a), shr(255, b))):", left, t2);
left = gasleft();
bool t3 = checkSameSign3(a, b);
left = left - gasleft();
console2.log("eq(shr(255, a), shr(255, b)): ", left, t3);
left = gasleft();
bool t4 = checkSameSign4(a, b);
left = left - gasleft();
console2.log("iszero(shr(255, xor(b, a))): ", left, t4);
left = gasleft();
bool t5 = checkSameSign5(a, b);
left = left - gasleft();
console2.log("lt(xor(a, b), 0x800000...): ", left, t5);
assert(t1 == t2 && t2 == t3 && t3 == t4 && t4 == t5);
}
// -----------------------------------------------------------------------------
// prerequisites:
// -----------------------------------------------------------------------------
// 1: install foundry
// 2: install forge-std:
// $ forge install foundry-rs/forge-std
// -----------------------------------------------------------------------------
// run fuzz test:
// -----------------------------------------------------------------------------
// forge test -m test__checkSameSign
contract Test__checkSameSign is Test {
function test__checkSameSign(int256 a, int256 b) public view {
execute(a, b);
}
}
// -----------------------------------------------------------------------------
// generate gas output:
// -----------------------------------------------------------------------------
// FOUNDRY_PROFILE="optim-off" forge script ./test/CheckSameSign.sol --tc Script__checkSameSign
// FOUNDRY_PROFILE="optim-on" forge script ./test/CheckSameSign.sol --tc Script__checkSameSign
contract Script__checkSameSign is Script {
function run() public view {
execute(int256((type(int96).max) * -1), int256((type(int96).max)));
}
}
[optim-on]
test = 'test'
libs = ['lib']
optimizer = true
optimizer_runs = 10000000
solc_version = '0.8.15'
fuzz_runs = 10000000
[optim-off]
test = 'test'
libs = ['lib']
optimizer = false
solc_version = '0.8.15'
fuzz_runs = 10000000
forge-std/=lib/forge-std/src/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment