SafeCast库提供了solidity的基础整数类型uintX和intX之间的类型安全转换的库方法。在不同的类型转换之间都加入溢出检查,如果一旦在转换过程中出现类型的溢出会立刻revert。
[openzeppelin]:v4.8.3,[forge-std]:v1.5.6
Github: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.3/contracts/utils/math/SafeCast.sol
SafeCast库提供了solidity的基础整数类型uintX和intX之间的类型安全转换的库方法。在不同的类型转换之间都加入溢出检查,如果一旦在转换过程中出现类型的溢出会立刻revert。
solidity中从uint256/int256向位数更小的整形做类型转换时可能会在小位数的整形上出现溢出,但是solidity是不会revert的。这种solidity的默认行为很容易产生bug。如果你的程序中有使用到uint256/int256向低位数整数的转换,推荐在每一处类型转换的地方使用SafeCast库。
封装SafeCast library成为一个可调用合约:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "openzeppelin-contracts/contracts/utils/math/SafeCast.sol";
contract MockSafeCast {
using SafeCast for uint;
using SafeCast for int;
function toUint248(uint256 value) external pure returns (uint248) {
return value.toUint248();
}
function toUint240(uint256 value) external pure returns (uint240) {
return value.toUint240();
}
function toUint232(uint256 value) external pure returns (uint232){
return value.toUint232();
}
function toUint224(uint256 value) external pure returns (uint224){
return value.toUint224();
}
function toUint216(uint256 value) external pure returns (uint216){
return value.toUint216();
}
function toUint208(uint256 value) external pure returns (uint208){
return value.toUint208();
}
function toUint200(uint256 value) external pure returns (uint200){
return value.toUint200();
}
function toUint192(uint256 value) external pure returns (uint192) {
return value.toUint192();
}
function toUint184(uint256 value) external pure returns (uint184){
return value.toUint184();
}
function toUint176(uint256 value) external pure returns (uint176){
return value.toUint176();
}
function toUint168(uint256 value) external pure returns (uint168){
return value.toUint168();
}
function toUint160(uint256 value) external pure returns (uint160){
return value.toUint160();
}
function toUint152(uint256 value) external pure returns (uint152){
return value.toUint152();
}
function toUint144(uint256 value) external pure returns (uint144){
return value.toUint144();
}
function toUint136(uint256 value) external pure returns (uint136){
return value.toUint136();
}
function toUint128(uint256 value) external pure returns (uint128) {
return value.toUint128();
}
function toUint120(uint256 value) external pure returns (uint120) {
return value.toUint120();
}
function toUint112(uint256 value) external pure returns (uint112) {
return value.toUint112();
}
function toUint104(uint256 value) external pure returns (uint104) {
return value.toUint104();
}
function toUint96(uint256 value) external pure returns (uint96){
return value.toUint96();
}
function toUint88(uint256 value) external pure returns (uint88){
return value.toUint88();
}
function toUint80(uint256 value) external pure returns (uint80){
return value.toUint80();
}
function toUint72(uint256 value) external pure returns (uint72){
return value.toUint72();
}
function toUint64(uint256 value) external pure returns (uint64){
return value.toUint64();
}
function toUint56(uint256 value) external pure returns (uint56) {
return value.toUint56();
}
function toUint48(uint256 value) external pure returns (uint48){
return value.toUint48();
}
function toUint40(uint256 value) external pure returns (uint40){
return value.toUint40();
}
function toUint32(uint256 value) external pure returns (uint32) {
return value.toUint32();
}
function toUint24(uint256 value) external pure returns (uint24){
return value.toUint24();
}
function toUint16(uint256 value) external pure returns (uint16){
return value.toUint16();
}
function toUint8(uint256 value) external pure returns (uint8){
return value.toUint8();
}
function toUint256(int256 value) internal pure returns (uint256) {
return value.toUint256();
}
function toInt248(int256 value) internal pure returns (int248){
return value.toInt248();
}
function toInt240(int256 value) internal pure returns (int240){
return value.toInt240();
}
function toInt232(int256 value) internal pure returns (int232){
return value.toInt232();
}
function toInt224(int256 value) internal pure returns (int224) {
return value.toInt224();
}
function toInt216(int256 value) internal pure returns (int216) {
return value.toInt216();
}
function toInt208(int256 value) internal pure returns (int208) {
return value.toInt208();
}
function toInt200(int256 value) internal pure returns (int200) {
return value.toInt200();
}
function toInt192(int256 value) internal pure returns (int192) {
return value.toInt192();
}
function toInt184(int256 value) internal pure returns (int184) {
return value.toInt184();
}
function toInt176(int256 value) internal pure returns (int176) {
return value.toInt176();
}
function toInt168(int256 value) internal pure returns (int168) {
return value.toInt168();
}
function toInt160(int256 value) internal pure returns (int160) {
return value.toInt160();
}
function toInt152(int256 value) internal pure returns (int152) {
return value.toInt152();
}
function toInt144(int256 value) internal pure returns (int144) {
return value.toInt144();
}
function toInt136(int256 value) internal pure returns (int136) {
return value.toInt136();
}
function toInt128(int256 value) internal pure returns (int128) {
return value.toInt128();
}
function toInt120(int256 value) internal pure returns (int120) {
return value.toInt120();
}
function toInt112(int256 value) internal pure returns (int112) {
return value.toInt112();
}
function toInt104(int256 value) internal pure returns (int104) {
return value.toInt104();
}
function toInt96(int256 value) internal pure returns (int96) {
return value.toInt96();
}
function toInt88(int256 value) internal pure returns (int88) {
return value.toInt88();
}
function toInt80(int256 value) internal pure returns (int80) {
return value.toInt80();
}
function toInt72(int256 value) internal pure returns (int72) {
return value.toInt72();
}
function toInt64(int256 value) internal pure returns (int64) {
return value.toInt64();
}
function toInt56(int256 value) internal pure returns (int56) {
return value.toInt56();
}
function toInt48(int256 value) internal pure returns (int48) {
return value.toInt48();
}
function toInt40(int256 value) internal pure returns (int40) {
return value.toInt40();
}
function toInt32(int256 value) internal pure returns (int32){
return value.toInt32();
}
function toInt24(int256 value) internal pure returns (int24){
return value.toInt24();
}
function toInt16(int256 value) internal pure returns (int16) {
return value.toInt16();
}
function toInt8(int256 value) internal pure returns (int8){
return value.toInt8();
}
function toInt256(uint256 value) internal pure returns (int256) {
return value.toInt256();
}
}
全部foundry测试合约:
SafeCast库中函数众多,但是可以按照以下类别分组:
这样,通过组合使用该库的库函数,就可以将uint256或int256安全地转换成各种小位数的有符号或无符号整形。
以uint256 -> uint248举例:
function toUint248(uint256 value) internal pure returns (uint248) {
// 判断输入的uint256的值<=uint248类型的最大值,这样才能保证在类型转换的过程中不发生溢出
// 如果不满足value>uint248类型的最大值,revert
require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
// 类型转换,从uint256转换为uint248
return uint248(value);
}
foundry代码验证
contract SafeCastTest is Test {
MockSafeCast msf = new MockSafeCast();
function test_ToUint248() external {
uint maxUint248 = type(uint248).max;
assertEq(msf.toUint248(0), 0);
assertEq(msf.toUint248(1), 1);
assertEq(msf.toUint248(maxUint248), uint248(maxUint248));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 248 bits");
msf.toUint248(maxUint248 + 1);
}
function test_ToUint240() external {
uint maxUint240 = type(uint240).max;
assertEq(msf.toUint240(0), 0);
assertEq(msf.toUint240(1), 1);
assertEq(msf.toUint240(maxUint240), uint240(maxUint240));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 240 bits");
msf.toUint240(maxUint240 + 1);
}
function test_ToUint232() external {
uint maxUint232 = type(uint232).max;
assertEq(msf.toUint232(0), 0);
assertEq(msf.toUint232(1), 1);
assertEq(msf.toUint232(maxUint232), uint232(maxUint232));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 232 bits");
msf.toUint232(maxUint232 + 1);
}
function test_ToUint224() external {
uint maxUint224 = type(uint224).max;
assertEq(msf.toUint224(0), 0);
assertEq(msf.toUint224(1), 1);
assertEq(msf.toUint224(maxUint224), uint224(maxUint224));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 224 bits");
msf.toUint224(maxUint224 + 1);
}
function test_ToUint216() external {
uint maxUint216 = type(uint216).max;
assertEq(msf.toUint216(0), 0);
assertEq(msf.toUint216(1), 1);
assertEq(msf.toUint216(maxUint216), uint216(maxUint216));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 216 bits");
msf.toUint216(maxUint216 + 1);
}
function test_ToUint208() external {
uint maxUint208 = type(uint208).max;
assertEq(msf.toUint208(0), 0);
assertEq(msf.toUint208(1), 1);
assertEq(msf.toUint208(maxUint208), uint208(maxUint208));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 208 bits");
msf.toUint208(maxUint208 + 1);
}
function test_ToUint200() external {
uint maxUint200 = type(uint200).max;
assertEq(msf.toUint200(0), 0);
assertEq(msf.toUint200(1), 1);
assertEq(msf.toUint200(maxUint200), uint200(maxUint200));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 200 bits");
msf.toUint200(maxUint200 + 1);
}
function test_ToUint192() external {
uint maxUint192 = type(uint192).max;
assertEq(msf.toUint192(0), 0);
assertEq(msf.toUint192(1), 1);
assertEq(msf.toUint192(maxUint192), uint192(maxUint192));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 192 bits");
msf.toUint192(maxUint192 + 1);
}
function test_ToUint184() external {
uint maxUint184 = type(uint184).max;
assertEq(msf.toUint184(0), 0);
assertEq(msf.toUint184(1), 1);
assertEq(msf.toUint184(maxUint184), uint184(maxUint184));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 184 bits");
msf.toUint184(maxUint184 + 1);
}
function test_ToUint176() external {
uint maxUint176 = type(uint176).max;
assertEq(msf.toUint176(0), 0);
assertEq(msf.toUint176(1), 1);
assertEq(msf.toUint176(maxUint176), uint176(maxUint176));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 176 bits");
msf.toUint176(maxUint176 + 1);
}
function test_ToUint168() external {
uint maxUint168 = type(uint168).max;
assertEq(msf.toUint168(0), 0);
assertEq(msf.toUint168(1), 1);
assertEq(msf.toUint168(maxUint168), uint168(maxUint168));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 168 bits");
msf.toUint168(maxUint168 + 1);
}
function test_ToUint160() external {
uint maxUint160 = type(uint160).max;
assertEq(msf.toUint160(0), 0);
assertEq(msf.toUint160(1), 1);
assertEq(msf.toUint160(maxUint160), uint160(maxUint160));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 160 bits");
msf.toUint160(maxUint160 + 1);
}
function test_ToUint152() external {
uint maxUint152 = type(uint152).max;
assertEq(msf.toUint152(0), 0);
assertEq(msf.toUint152(1), 1);
assertEq(msf.toUint152(maxUint152), uint152(maxUint152));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 152 bits");
msf.toUint152(maxUint152 + 1);
}
function test_ToUint144() external {
uint maxUint144 = type(uint144).max;
assertEq(msf.toUint144(0), 0);
assertEq(msf.toUint144(1), 1);
assertEq(msf.toUint144(maxUint144), uint144(maxUint144));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 144 bits");
msf.toUint144(maxUint144 + 1);
}
function test_ToUint136() external {
uint maxUint136 = type(uint136).max;
assertEq(msf.toUint136(0), 0);
assertEq(msf.toUint136(1), 1);
assertEq(msf.toUint136(maxUint136), uint136(maxUint136));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 136 bits");
msf.toUint136(maxUint136 + 1);
}
function test_ToUint128() external {
uint maxUint128 = type(uint128).max;
assertEq(msf.toUint128(0), 0);
assertEq(msf.toUint128(1), 1);
assertEq(msf.toUint128(maxUint128), uint128(maxUint128));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 128 bits");
msf.toUint128(maxUint128 + 1);
}
function test_ToUint120() external {
uint maxUint120 = type(uint120).max;
assertEq(msf.toUint120(0), 0);
assertEq(msf.toUint120(1), 1);
assertEq(msf.toUint120(maxUint120), uint120(maxUint120));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 120 bits");
msf.toUint120(maxUint120 + 1);
}
function test_ToUint112() external {
uint maxUint112 = type(uint112).max;
assertEq(msf.toUint112(0), 0);
assertEq(msf.toUint112(1), 1);
assertEq(msf.toUint112(maxUint112), uint112(maxUint112));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 112 bits");
msf.toUint112(maxUint112 + 1);
}
function test_ToUint104() external {
uint maxUint104 = type(uint104).max;
assertEq(msf.toUint104(0), 0);
assertEq(msf.toUint104(1), 1);
assertEq(msf.toUint104(maxUint104), uint104(maxUint104));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 104 bits");
msf.toUint104(maxUint104 + 1);
}
function test_ToUint96() external {
uint maxUint96 = type(uint96).max;
assertEq(msf.toUint96(0), 0);
assertEq(msf.toUint96(1), 1);
assertEq(msf.toUint96(maxUint96), uint96(maxUint96));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 96 bits");
msf.toUint96(maxUint96 + 1);
}
function test_ToUint88() external {
uint maxUint88 = type(uint88).max;
assertEq(msf.toUint88(0), 0);
assertEq(msf.toUint88(1), 1);
assertEq(msf.toUint88(maxUint88), uint88(maxUint88));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 88 bits");
msf.toUint88(maxUint88 + 1);
}
function test_ToUint80() external {
uint maxUint80 = type(uint80).max;
assertEq(msf.toUint80(0), 0);
assertEq(msf.toUint80(1), 1);
assertEq(msf.toUint80(maxUint80), uint80(maxUint80));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 80 bits");
msf.toUint80(maxUint80 + 1);
}
function test_ToUint72() external {
uint maxUint72 = type(uint72).max;
assertEq(msf.toUint72(0), 0);
assertEq(msf.toUint72(1), 1);
assertEq(msf.toUint72(maxUint72), uint72(maxUint72));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 72 bits");
msf.toUint72(maxUint72 + 1);
}
function test_ToUint64() external {
uint maxUint64 = type(uint64).max;
assertEq(msf.toUint64(0), 0);
assertEq(msf.toUint64(1), 1);
assertEq(msf.toUint64(maxUint64), uint64(maxUint64));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 64 bits");
msf.toUint64(maxUint64 + 1);
}
function test_ToUint56() external {
uint maxUint56 = type(uint56).max;
assertEq(msf.toUint56(0), 0);
assertEq(msf.toUint56(1), 1);
assertEq(msf.toUint56(maxUint56), uint56(maxUint56));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 56 bits");
msf.toUint56(maxUint56 + 1);
}
function test_ToUint48() external {
uint maxUint48 = type(uint48).max;
assertEq(msf.toUint48(0), 0);
assertEq(msf.toUint48(1), 1);
assertEq(msf.toUint48(maxUint48), uint48(maxUint48));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 48 bits");
msf.toUint48(maxUint48 + 1);
}
function test_ToUint40() external {
uint maxUint40 = type(uint40).max;
assertEq(msf.toUint40(0), 0);
assertEq(msf.toUint40(1), 1);
assertEq(msf.toUint40(maxUint40), uint40(maxUint40));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 40 bits");
msf.toUint40(maxUint40 + 1);
}
function test_ToUint32() external {
uint maxUint32 = type(uint32).max;
assertEq(msf.toUint32(0), 0);
assertEq(msf.toUint32(1), 1);
assertEq(msf.toUint32(maxUint32), uint32(maxUint32));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 32 bits");
msf.toUint32(maxUint32 + 1);
}
function test_ToUint24() external {
uint maxUint24 = type(uint24).max;
assertEq(msf.toUint24(0), 0);
assertEq(msf.toUint24(1), 1);
assertEq(msf.toUint24(maxUint24), uint24(maxUint24));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 24 bits");
msf.toUint24(maxUint24 + 1);
}
function test_ToUint16() external {
uint maxUint16 = type(uint16).max;
assertEq(msf.toUint16(0), 0);
assertEq(msf.toUint16(1), 1);
assertEq(msf.toUint16(maxUint16), uint16(maxUint16));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 16 bits");
msf.toUint16(maxUint16 + 1);
}
function test_ToUint8() external {
uint maxUint8 = type(uint8).max;
assertEq(msf.toUint8(0), 0);
assertEq(msf.toUint8(1), 1);
assertEq(msf.toUint8(maxUint8), uint8(maxUint8));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 8 bits");
msf.toUint8(maxUint8 + 1);
}
}
以int256 -> int248举例:
function toInt248(int256 value) internal pure returns (int248 downcasted) {
// downcasted为直接做有符号整数向小位数有符号整数的类型强转
downcasted = int248(value);
// 要求转换后的有符号整形同转换前相等,否则就是在转换的过程中产生了溢出
require(downcasted == value, "SafeCast: value doesn't fit in 248 bits");
}
注:当输入值value的值大于int248的最大值或小于int248的最小值时,进行类型转换时会产生溢出。
foundry代码验证
contract SafeCastTest is Test {
MockSafeCast msf = new MockSafeCast();
function test_ToInt248() external {
int maxInt248 = type(int248).max;
int minInt248 = type(int248).min;
assertEq(msf.toInt248(0), 0);
assertEq(msf.toInt248(1), 1);
assertEq(msf.toInt248(maxInt248), int248(maxInt248));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 248 bits");
msf.toInt248(maxInt248 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 248 bits");
msf.toInt248(minInt248 - 1);
}
function test_ToInt240() external {
int maxInt240 = type(int240).max;
int minInt240 = type(int240).min;
assertEq(msf.toInt240(0), 0);
assertEq(msf.toInt240(1), 1);
assertEq(msf.toInt240(maxInt240), int240(maxInt240));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 240 bits");
msf.toInt240(maxInt240 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 240 bits");
msf.toInt240(minInt240 - 1);
}
function test_ToInt232() external {
int maxInt232 = type(int232).max;
int minInt232 = type(int232).min;
assertEq(msf.toInt232(0), 0);
assertEq(msf.toInt232(1), 1);
assertEq(msf.toInt232(maxInt232), int232(maxInt232));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 232 bits");
msf.toInt232(maxInt232 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 232 bits");
msf.toInt232(minInt232 - 1);
}
function test_ToInt224() external {
int maxInt224 = type(int224).max;
int minInt224 = type(int224).min;
assertEq(msf.toInt224(0), 0);
assertEq(msf.toInt224(1), 1);
assertEq(msf.toInt224(maxInt224), int224(maxInt224));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 224 bits");
msf.toInt224(maxInt224 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 224 bits");
msf.toInt224(minInt224 - 1);
}
function test_ToInt216() external {
int maxInt216 = type(int216).max;
int minInt216 = type(int216).min;
assertEq(msf.toInt216(0), 0);
assertEq(msf.toInt216(1), 1);
assertEq(msf.toInt216(maxInt216), int216(maxInt216));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 216 bits");
msf.toInt216(maxInt216 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 216 bits");
msf.toInt216(minInt216 - 1);
}
function test_ToInt208() external {
int maxInt208 = type(int208).max;
int minInt208 = type(int208).min;
assertEq(msf.toInt208(0), 0);
assertEq(msf.toInt208(1), 1);
assertEq(msf.toInt208(maxInt208), int208(maxInt208));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 208 bits");
msf.toInt208(maxInt208 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 208 bits");
msf.toInt208(minInt208 - 1);
}
function test_ToInt200() external {
int maxInt200 = type(int200).max;
int minInt200 = type(int200).min;
assertEq(msf.toInt200(0), 0);
assertEq(msf.toInt200(1), 1);
assertEq(msf.toInt200(maxInt200), int200(maxInt200));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 200 bits");
msf.toInt200(maxInt200 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 200 bits");
msf.toInt200(minInt200 - 1);
}
function test_ToInt192() external {
int maxInt192 = type(int192).max;
int minInt192 = type(int192).min;
assertEq(msf.toInt192(0), 0);
assertEq(msf.toInt192(1), 1);
assertEq(msf.toInt192(maxInt192), int192(maxInt192));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 192 bits");
msf.toInt192(maxInt192 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 192 bits");
msf.toInt192(minInt192 - 1);
}
function test_ToInt184() external {
int maxInt184 = type(int184).max;
int minInt184 = type(int184).min;
assertEq(msf.toInt184(0), 0);
assertEq(msf.toInt184(1), 1);
assertEq(msf.toInt184(maxInt184), int184(maxInt184));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 184 bits");
msf.toInt184(maxInt184 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 184 bits");
msf.toInt184(minInt184 - 1);
}
function test_ToInt176() external {
int maxInt176 = type(int176).max;
int minInt176 = type(int176).min;
assertEq(msf.toInt176(0), 0);
assertEq(msf.toInt176(1), 1);
assertEq(msf.toInt176(maxInt176), int176(maxInt176));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 176 bits");
msf.toInt176(maxInt176 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 176 bits");
msf.toInt176(minInt176 - 1);
}
function test_ToInt168() external {
int maxInt168 = type(int168).max;
int minInt168 = type(int168).min;
assertEq(msf.toInt168(0), 0);
assertEq(msf.toInt168(1), 1);
assertEq(msf.toInt168(maxInt168), int168(maxInt168));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 168 bits");
msf.toInt168(maxInt168 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 168 bits");
msf.toInt168(minInt168 - 1);
}
function test_ToInt160() external {
int maxInt160 = type(int160).max;
int minInt160 = type(int160).min;
assertEq(msf.toInt160(0), 0);
assertEq(msf.toInt160(1), 1);
assertEq(msf.toInt160(maxInt160), int160(maxInt160));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 160 bits");
msf.toInt160(maxInt160 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 160 bits");
msf.toInt160(minInt160 - 1);
}
function test_ToInt152() external {
int maxInt152 = type(int152).max;
int minInt152 = type(int152).min;
assertEq(msf.toInt152(0), 0);
assertEq(msf.toInt152(1), 1);
assertEq(msf.toInt152(maxInt152), int152(maxInt152));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 152 bits");
msf.toInt152(maxInt152 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 152 bits");
msf.toInt152(minInt152 - 1);
}
function test_ToInt144() external {
int maxInt144 = type(int144).max;
int minInt144 = type(int144).min;
assertEq(msf.toInt144(0), 0);
assertEq(msf.toInt144(1), 1);
assertEq(msf.toInt144(maxInt144), int144(maxInt144));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 144 bits");
msf.toInt144(maxInt144 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 144 bits");
msf.toInt144(minInt144 - 1);
}
function test_ToInt136() external {
int maxInt136 = type(int136).max;
int minInt136 = type(int136).min;
assertEq(msf.toInt136(0), 0);
assertEq(msf.toInt136(1), 1);
assertEq(msf.toInt136(maxInt136), int136(maxInt136));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 136 bits");
msf.toInt136(maxInt136 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 136 bits");
msf.toInt136(minInt136 - 1);
}
function test_ToInt128() external {
int maxInt128 = type(int128).max;
int minInt128 = type(int128).min;
assertEq(msf.toInt128(0), 0);
assertEq(msf.toInt128(1), 1);
assertEq(msf.toInt128(maxInt128), int128(maxInt128));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 128 bits");
msf.toInt128(maxInt128 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 128 bits");
msf.toInt128(minInt128 - 1);
}
function test_ToInt120() external {
int maxInt120 = type(int120).max;
int minInt120 = type(int120).min;
assertEq(msf.toInt120(0), 0);
assertEq(msf.toInt120(1), 1);
assertEq(msf.toInt120(maxInt120), int120(maxInt120));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 120 bits");
msf.toInt120(maxInt120 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 120 bits");
msf.toInt120(minInt120 - 1);
}
function test_ToInt112() external {
int maxInt112 = type(int112).max;
int minInt112 = type(int112).min;
assertEq(msf.toInt112(0), 0);
assertEq(msf.toInt112(1), 1);
assertEq(msf.toInt112(maxInt112), int112(maxInt112));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 112 bits");
msf.toInt112(maxInt112 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 112 bits");
msf.toInt112(minInt112 - 1);
}
function test_ToInt104() external {
int maxInt104 = type(int104).max;
int minInt104 = type(int104).min;
assertEq(msf.toInt104(0), 0);
assertEq(msf.toInt104(1), 1);
assertEq(msf.toInt104(maxInt104), int104(maxInt104));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 104 bits");
msf.toInt104(maxInt104 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 104 bits");
msf.toInt104(minInt104 - 1);
}
function test_ToInt96() external {
int maxInt96 = type(int96).max;
int minInt96 = type(int96).min;
assertEq(msf.toInt96(0), 0);
assertEq(msf.toInt96(1), 1);
assertEq(msf.toInt96(maxInt96), int96(maxInt96));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 96 bits");
msf.toInt96(maxInt96 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 96 bits");
msf.toInt96(minInt96 - 1);
}
function test_ToInt88() external {
int maxInt88 = type(int88).max;
int minInt88 = type(int88).min;
assertEq(msf.toInt88(0), 0);
assertEq(msf.toInt88(1), 1);
assertEq(msf.toInt88(maxInt88), int88(maxInt88));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 88 bits");
msf.toInt88(maxInt88 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 88 bits");
msf.toInt88(minInt88 - 1);
}
function test_ToInt80() external {
int maxInt80 = type(int80).max;
int minInt80 = type(int80).min;
assertEq(msf.toInt80(0), 0);
assertEq(msf.toInt80(1), 1);
assertEq(msf.toInt80(maxInt80), int80(maxInt80));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 80 bits");
msf.toInt80(maxInt80 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 80 bits");
msf.toInt80(minInt80 - 1);
}
function test_ToInt72() external {
int maxInt72 = type(int72).max;
int minInt72 = type(int72).min;
assertEq(msf.toInt72(0), 0);
assertEq(msf.toInt72(1), 1);
assertEq(msf.toInt72(maxInt72), int72(maxInt72));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 72 bits");
msf.toInt72(maxInt72 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 72 bits");
msf.toInt72(minInt72 - 1);
}
function test_ToInt64() external {
int maxInt64 = type(int64).max;
int minInt64 = type(int64).min;
assertEq(msf.toInt64(0), 0);
assertEq(msf.toInt64(1), 1);
assertEq(msf.toInt64(maxInt64), int64(maxInt64));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 64 bits");
msf.toInt64(maxInt64 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 64 bits");
msf.toInt64(minInt64 - 1);
}
function test_ToInt56() external {
int maxInt56 = type(int56).max;
int minInt56 = type(int56).min;
assertEq(msf.toInt56(0), 0);
assertEq(msf.toInt56(1), 1);
assertEq(msf.toInt56(maxInt56), int56(maxInt56));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 56 bits");
msf.toInt56(maxInt56 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 56 bits");
msf.toInt56(minInt56 - 1);
}
function test_ToInt48() external {
int maxInt48 = type(int48).max;
int minInt48 = type(int48).min;
assertEq(msf.toInt48(0), 0);
assertEq(msf.toInt48(1), 1);
assertEq(msf.toInt48(maxInt48), int48(maxInt48));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 48 bits");
msf.toInt48(maxInt48 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 48 bits");
msf.toInt48(minInt48 - 1);
}
function test_ToInt40() external {
int maxInt40 = type(int40).max;
int minInt40 = type(int40).min;
assertEq(msf.toInt40(0), 0);
assertEq(msf.toInt40(1), 1);
assertEq(msf.toInt40(maxInt40), int40(maxInt40));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 40 bits");
msf.toInt40(maxInt40 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 40 bits");
msf.toInt40(minInt40 - 1);
}
function test_ToInt32() external {
int maxInt32 = type(int32).max;
int minInt32 = type(int32).min;
assertEq(msf.toInt32(0), 0);
assertEq(msf.toInt32(1), 1);
assertEq(msf.toInt32(maxInt32), int32(maxInt32));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 32 bits");
msf.toInt32(maxInt32 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 32 bits");
msf.toInt32(minInt32 - 1);
}
function test_ToInt24() external {
int maxInt24 = type(int24).max;
int minInt24 = type(int24).min;
assertEq(msf.toInt24(0), 0);
assertEq(msf.toInt24(1), 1);
assertEq(msf.toInt24(maxInt24), int24(maxInt24));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 24 bits");
msf.toInt24(maxInt24 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 24 bits");
msf.toInt24(minInt24 - 1);
}
function test_ToInt16() external {
int maxInt16 = type(int16).max;
int minInt16 = type(int16).min;
assertEq(msf.toInt16(0), 0);
assertEq(msf.toInt16(1), 1);
assertEq(msf.toInt16(maxInt16), int16(maxInt16));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 16 bits");
msf.toInt16(maxInt16 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 16 bits");
msf.toInt16(minInt16 - 1);
}
function test_ToInt8() external {
int maxInt8 = type(int8).max;
int minInt8 = type(int8).min;
assertEq(msf.toInt8(0), 0);
assertEq(msf.toInt8(1), 1);
assertEq(msf.toInt8(maxInt8), int8(maxInt8));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in 8 bits");
msf.toInt8(maxInt8 + 1);
vm.expectRevert("SafeCast: value doesn't fit in 8 bits");
msf.toInt8(minInt8 - 1);
}
}
toUint256(int256 value)
: int256的value转换成uint256 function toUint256(int256 value) internal pure returns (uint256) {
// 要求value必须>=0,因为uint256无负数
require(value >= 0, "SafeCast: value must be positive");
// 只要value是正数,那么int256向uint256的转换就不会发生溢出。因为int256的正数域是uint256值域的一个真子集。所以可以安全地直接返回转换值
return uint256(value);
}
toInt256(uint256 value)
: uint256的value转换成int256 function toInt256(uint256 value) internal pure returns (int256) {
// 要求输入value的值必须<=int256的最大值,这样就可以保证在uint256向int256转换的过程中不发生溢出
require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
// 返回int256的直接强转值
return int256(value);
}
foundry代码验证
contract MathTest is Test {
MockSafeCast msf = new MockSafeCast();
function test_toUint256() external {
int maxInt256 = type(int).max;
assertEq(msf.toUint256(0), 0);
assertEq(msf.toUint256(1), 1);
assertEq(msf.toUint256(maxInt256), uint(maxInt256));
// revert with overflow
vm.expectRevert("SafeCast: value must be positive");
msf.toUint256(- 1);
}
function test_toInt256() external {
uint maxInt256 = uint(type(int).max);
assertEq(msf.toInt256(0), 0);
assertEq(msf.toInt256(1), 1);
assertEq(msf.toInt256(maxInt256), int(maxInt256));
// revert with overflow
vm.expectRevert("SafeCast: value doesn't fit in an int256");
msf.toInt256(maxInt256 + 1);
}
}
ps:\ 本人热爱图灵,热爱中本聪,热爱V神。 以下是我个人的公众号,如果有技术问题可以关注我的公众号来跟我交流。 同时我也会在这个公众号上每周更新我的原创文章,喜欢的小伙伴或者老伙计可以支持一下! 如果需要转发,麻烦注明作者。十分感谢!
公众号名称:后现代泼痞浪漫主义奠基人
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!