BoredApeYachtclub的合约代码中数值运算在新版solc编译后运行出错我今天学习一下NFT的代码,里面有个数值运算的函数,用于生成每个NFTid对应的url.有个函数负责讲id转换成字符串.比如123变成'123'.silidity本身没有实现uint=>stri
我今天学习一下NFT 的代码,里面有个数值运算的函数,用于生成每个NFT id对应的url. 有个函数负责讲id 转换成字符串.比如 123 变成'123'. silidity 本身没有实现uint => string的转换,因此需要自己编写代码转换
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev String operations.
*/
library Strings {
/**
* @dev Converts a `uint256` to its ASCII `string` representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
uint256 index = digits - 1;
temp = value;
while (temp != 0) {
buffer[index--] = bytes1(uint8(48 + temp % 10));
temp /= 10;
}
return string(buffer);
}
}
我自己编写了几个由数字转换成字符串的solidity函数,想对比一下gas开销. 但是这个函数在0.8.17 的slidity编译出来, 在evm 里面执行的时候,这个toString 函数总是会失败.
今天调试了半天,最后相同,因为这里面的index 会出现变成 0 -- 场景,引发参数越界,因此计算错误. boredape 以前的版本,没有越界检查,就不会出错.
下面的 toString() 来自无聊猿引用(oraclize/ethereum-api), toString2() 和toString3() 是我写的,开的内存更大,但是不先计算总共几个数字. 结果还是这个toString的gas开销更小.
//SPDX-License-Identifier:MIT
pragma solidity >0.8.0;
contract StringUtil{
function getDigits(uint256 temp) public pure returns (uint256 digits){
while (temp != 0) {
digits++;
temp /= 10;
}
}
//gas 3731 6133
function toString(uint256 value) public pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
uint256 index = digits - 1;
temp = value;
while (temp != 0) {
buffer[index] = bytes1(uint8(48 + temp % 10));
if(index >0) index --;
temp /= 10;
}
return string(buffer);
}
function sliceToString( bytes calldata arr , uint start ) pure external returns (string memory){
return string(arr[start:]);
}
//gas 6730 8444
function toString2(uint256 _num ) public view returns (string memory){
if(_num == 0) return "0";
bytes memory arr = new bytes (78); // utin256 max 1.15e77
uint256 curr = _num;
uint i ;
for( i = arr.length -1 ; i >= 0 && curr > 0 ; -- i){
arr[i] = bytes1(uint8( curr % 10) + uint8(0x30));// digit + '0'
curr = curr / 10;
}
return this.sliceToString(arr,i + 1);
}
//4755(2digit) 7451(4 digit)
function toString3(uint256 _num ) public pure returns (string memory){
if(_num == 0) return "0";
bytes memory arr = new bytes (78); // utin256 max 1.15e77
uint256 curr = _num;
uint i ;
for( i = arr.length -1 ; i >= 0 && curr > 0 ; -- i){
arr[i] = bytes1(uint8( curr % 10) + uint8(0x30));// digit + '0'
curr = curr / 10;
}
i += 1;
bytes memory ret = new bytes(arr.length - i);
for(uint j = 0 ; j < ret.length; ++ j){
ret[j] = arr[j + i];
}
return string(ret);
}
}
BoreApe的合约代码连接: <!--StartFragment-->
Bored Ape Yacht Club: BAYC Token | Address 0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d | Etherscan
<!--EndFragment-->
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!