以太坊智能合約 ABI編碼,動態類型string,函數參數的ABI編碼, 含c++代碼

官方文檔講得不全也不是很清楚,特別是動態類型string。這裏補充。

以太坊的智能合約ABI編碼,官方文檔和說明:https://solidity.readthedocs.io/en/v0.6.8/abi-spec.html

一個實用的工具,可直接生成ABI編碼。
比如下圖使用
在這裏插入圖片描述
這裏側重於solidity智能合約的構造方法的ABI編碼構造。

普通方法的編碼官網說得很清楚了。

構造函數的ABI編碼由兩部分構成,一是編譯後的智能合約代碼,而是構造函數的參數。

  1. 使用remix編譯智能合約,複製編譯後的十六進制碼。

在這裏插入圖片描述
2. 我們智能合約的構造方法是:

constructor (uint256 _deadline, uint32 _reward, string memory _code) public{

現在的問題是,如果我們使用後臺提交一個智能合約,需要提交該智能合約的構造函數的參數的值,但是,上面第一步的所複製的編碼中不包含參數的值,因此,需要我們自己構造構造函數的值的ABI編碼。

換一種說法描述上面的問題,如果使用remix部署我們上面的智能合約的話,因爲只有一個構造函數,且是帶參數的,因此deploy前需要填寫這些參數的值,如下圖。現在remix自動幫我們對參數進行ABI編碼了,並將它追加在第一步所複製的數據的後面。如果我們自己在後臺構造和部署智能合約,如何進行ABI編碼構造方法的參數?
在這裏插入圖片描述

  1. 根據constructor (uint256 _deadline, uint32 _reward, string memory _code) ,假如取值(3, 2, “helloworld”),第一個參數是uint256,0x0000000000000000000000000000000000000000000000000000000000000003,使用0填充,uint32同理,追加到前面的數中。第三個是string,動態類型,因此先填下面這個固定的數,以6爲開頭,長度爲64。6000000000000000000000000000000000000000000000000000000000000000,變成:

在這裏插入圖片描述
爲什麼要追加這個"60000000…"呢?看下文。
4. 接下來追加string的長度(使用16進製表示)用0填充前面部分;再追加字符串的16進製表示,用0填充後面部分。
在這裏插入圖片描述
5. 因爲0填充是以64長度爲單位的,因此,當字符串的16進制編碼長度操作了64長度,後面統一使用0填充。因此有
在這裏插入圖片描述

官網沒有說清楚的是,爲什麼要追加上面的值6000000000000000000000000000000000000000000000000000000000000000。如果有多於一個string參數,這個值就變了。本人覺得應該有更加詳細的關於ABI編碼的定義,基於目前現在這個已經足夠本人項目,因此不再深入查找。

謝謝

c++代碼


// deadline, uint256; reward, uint32, 
string appendParams_ABIEncode(string contractCode, unsigned long long deadline, unsigned int reward, string evalCode) {
	stringstream temp_time;
	temp_time << setfill('0') << setw(64) << hex << deadline;
	stringstream temp_reward;
	temp_reward << setfill('0') << setw(64) << hex << reward;

	stringstream temp_len;
	temp_len << setfill('0') << setw(64) << hex << evalCode.length();

	string code_hex = toHex(evalCode);
	int padding_num = code_hex.length() % 64;
	if (padding_num != 0) {
		padding_num = 64 - padding_num;
	}

	string padding = string(padding_num, '0');

	code_hex += padding;

	contractCode = contractCode 
		+ temp_time.str() 
		+ temp_reward.str() 
		//後面是字符串,動態空間,所以要加這個,沒在文檔中找到這個定義。https://abi.hashex.org/
		+ string("6000000000000000000000000000000000000000000000000000000000000000") 
		+ temp_len.str() + code_hex;
	return contractCode;
}

調用:

const string compiledCode = "";
string requestData = appendParams_ABIEncode(compiledCode, 20200529124532, 20, "dsfasdjfkldsjkaflksdjfljsdflksdj");

cout << requestData << endl;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章