目前也寫了很多智能合約了,經(jīng)過了幾次合約審計翠桦,總結(jié)一些值得優(yōu)化的點
拋出異常減少使用 require
疆股,應(yīng)該使用自定義 error
剛開始寫錯誤回調(diào)一直使用
require
來阻截并拋出錯誤日志抒巢,圖個方便伐脖,但是花費的Gas
相對應(yīng)的會升高,而使用自定義的error
能大量節(jié)省Gas
的消耗喷鸽,對開發(fā)人員來說众雷,編程方式也很簡單:
require(num != 1, 'ErrorMsg');
消耗 2578 Gas
error ErrorMsg(uint256 num);
消耗 2557 Gas
error ErrorMsg(uint256 num); //error需要寫在合約的外面
contract TestContract {
uint256 public num = 1;
function test() public view
{
require(num != 1, 'ErrorMsg'); //替換成下面這個
if(num == 1)
{
revert ErrorMsg(num);
}
}
}
使用枚舉管理狀態(tài)
在開發(fā)中,我習(xí)慣使用常量來管理一個記錄的狀態(tài)做祝,例如
STATUS_CANCELED = 0
&STATUS_STAKING = 1
砾省,但這同樣會造成 Gas 的提升,因此使用enum
枚舉來管理狀態(tài)會是個不錯的方式混槐。
enum Status (
Canceled, //默認的值為 0
Staking //默認的值為 1
)
{
status: Status.Staking, //使用方式
}
少用 for
循環(huán)
之前常用 for 循環(huán)去查詢一個地址底下所有的 tokenId 信息编兄,但是如果 NFT Mint 數(shù)量很多時,需要循環(huán)很多次才能總結(jié)出結(jié)果声登,就會造成 Gas 的增高狠鸳。建議使用
Mapping
去管理數(shù)據(jù),用多個Mapping
去控制地址所擁有的 TokenId 集合
mapping(address => uint256) public ownNum; //tokenId 所有用的數(shù)量
mapping(address => mapping(uint256 => uint256)) public tokenIds; //tokenId 所有用的數(shù)量
function mint() public
{
uint256 tokenId = 1;
_mint(tokenId); //mint方式
ownNum[地址] ++;
tokenIds[ownNum[地址]] = tokenId; //差不多這樣的意思
}
function getList(address _address) public
{
//盡量減少多個循環(huán)的使用悯嗓,如果必須用到for的話要注意管理循環(huán)次數(shù)碰煌,減少Gas
uint256 length = balanceOf(_address);
uint256[] memory result = new uint256[](length);
for (uint256 i = 0; i < length; i++)
result[i] = tokenIds(_address, i);
return result;
}
更新ing