solidity学習プロセス---abi符号化

5870 ワード

abi符号化関数


abiとは


アプリケーションバイナリインタフェース、イーサー坊の呼び出し契約時のインタフェースはABIが2つのプログラムモジュール間のインタフェースであることを示し、主にデータをソースコードとして符号化または復号するために使用されるコードである.イーサー坊で主にsolidity契約の関数呼び出しに用いられ,データの読み出しを逆符号化する方法

solidityABI符号化関数

  • abi.Encode(...)returns(bytes):計算パラメータのABI符号化.
  • abi.EncodePacked(...)returns(bytes):計算パラメータのコンパクトパッケージ符号化
  • abi. EncodeWithSelector(bytes 4 selector,...)returns(bytes):関数セレクタとパラメータを計算するABI符号化
  • abi.encodeWithSignature(string signature,...)returns(bytes):*abiに等しい.encodeWithSelector(bytes4(keccak256(signature), …)

  • solidityABI符号化関数実装の詳細


    関数セレクタ.公式ドキュメントでは、1つの関数呼び出しデータの最初の4バイトを定義し、呼び出す関数を指定します.これがある関数署名のKeccak(SHA-3)ハッシュの上位4バイト(上位左の大端順)である(訳注:ここで「上位左の大端順」とは、最上位バイトが最下位アドレスに格納されるシリアル化符号化方式、すなわち、上位バイトが左である). この署名は、関数名にカッコで囲まれたパラメータタイプのリストを加えたベースプロトタイプの仕様表現として定義され、パラメータタイプ間はカンマで区切られ、スペースはありません.
    簡単に言えば、関数セレクタは、関数名によってパラメータを識別し、異なる契約間の関数呼び出しに使用できます.
    1.契約における関数呼び出し呼び出し呼び出し呼び出しデータの最初の4バイト(0 x以降)は、関数名およびパラメータタイプを署名処理(Keccak–Sha 3)することである.
  • set(21)関数を実行すると、60 fe 47 b 1 set(uint 256)-関数署名ハッシュに切り取られた最初の4バイト(1バイトは16進数2文字)
  • が取得されます.
  • 入力パラメータ21対16進数15
  • 関数の最終結果:0 x 60 fe 47 b 10000000000000000000000000000000000000000000000000000000000015
  • 契約関数名と関数パラメータ、各パラメータは最終的に32バイトに補完されます.

    solidityABI符号化関数実装:

    contract testABI {
        uint storedData;
    
        function set(uint x) public {
            storedData = x;
        }
    
        function abiEncode() public view returns (bytes memory) {
            abi.encode(1);  //  1 ABI 
            return abi.encodeWithSignature("set(uint256)", 1); // set(uint256)  1  ABI  
        }
    }
    

    remix導入契約の後、abiEncode()を呼び出すと、次のデータ出力が生成されます.
  • abi.encode(21)

  • 0x60fe47b10000000000000000000000000000000000000000000000000000000000000015
  • そのうち60 fe 47 b 1が対応するset()関数の署名処理
    [
     {
     	"constant": false,
     	"inputs": [
     		{
     			"internalType": "uint256",
     			"name": "value",
     			"type": "uint256"
     		}
     	],
     	"name": "set",
     	"outputs": [],
     	"payable": false,
     	"stateMutability": "nonpayable",
     	"type": "function"
     }
    
  • である.
    ] ``

    abiDetail:

  • constant–関数がブロックチェーンの状態をtrueに変更した場合、falseは逆です.
  • type:呼び出しパラメータタイプ:string,function,callback,contsructor
  • name:呼び出しパラメータ名
  • payable:ether
  • をサポートするかどうか
  • stateMutability:(状態可変)-pure-view-payable-nonpayable
  • outputs:呼び出し出力値
  • input:{
  • name:パラメータ名
  • type:パラメータタイプ}

  • abi.encodeとabi.encodePacked

  • は関数をパッケージング処理するが、処理方式が異なり、32バイト未満のパラメータについては、前者はすべてのパラメータを32バイトに自動的に補完し、後者は
  • を自動的に補完しない.
  • uintのデフォルトはuint 256であり、検証時にバイトを補完するという問題は存在しない
  • contract TestDifference {
      function testUint(
        uint8 _num1,
        uint32 _num2
        )
        public view returns (bytes memory, bytes memory) {
        return (
          abi.encode(_num1),
          abi.encodePacked(_num2)
          );
      }
    
      function testBytes() public view returns (bytes memory, bytes memory) {
          bytes memory _bts ="Hello,world!";
        return (abi.encodePacked(_bts),abi.encode(_bts));
      }
    }
    

    abiの使用について.encodeWithSignature(string signature, …) returns (bytes)


    主な適用シーン:関数呼び出しかんすうよびだし
    contract Contract {
    
        MyContract contract1 = new MyContract();
    
        function getSelector() public view returns (bytes4, bytes4) {
            return (contract1.function1.selector, contract1.getBalance.selector);
        }
    
        function callGetValue(uint _x) public view returns (uint) {
    
            bytes4 selector = contract1.getValue.selector;
    
            bytes memory data = abi.encodeWithSelector(selector, _x);
            (bool success, bytes memory returnedData) = address(contract1).staticcall(data);
            require(success);
    
            return abi.decode(returnedData, (uint256));
        }
    }
    
    contract MyContract {
    
        function function1() public {}
    
        function getBalance(address _address) public view returns (uint256){}
    
        function getValue (uint _value) public pure returns (uint) {
            return _value;
        }
    
    }