Solidity

有沒有使用預編譯合約的例子?

  • January 13, 2020

問題是我想創建自己的自定義預編譯合約,並在我的私有乙太坊鏈中使用它。

是我的程式碼,但是當我呼叫hello.say()geth 附加行時它是不正確的。

在 geth 方面,我更改了core/vm/contracts.go文件,添加了我的自定義契約。

var PrecompiledContractsHomestead = map[common.Address]PrecompiledContract{
   common.BytesToAddress([]byte{1}): &ecrecover{},
   common.BytesToAddress([]byte{2}): &sha256hash{},
   common.BytesToAddress([]byte{3}): &ripemd160hash{},
   common.BytesToAddress([]byte{4}): &dataCopy{},
   common.BytesToAddress([]byte{10}): &nativehello{}, 
}

var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{
   common.BytesToAddress([]byte{1}): &ecrecover{},
   common.BytesToAddress([]byte{2}): &sha256hash{},
   common.BytesToAddress([]byte{3}): &ripemd160hash{},
   common.BytesToAddress([]byte{4}): &dataCopy{},
   common.BytesToAddress([]byte{5}): &bigModExp{},
   common.BytesToAddress([]byte{6}): &bn256AddByzantium{},
   common.BytesToAddress([]byte{7}): &bn256ScalarMulByzantium{},
   common.BytesToAddress([]byte{8}): &bn256PairingByzantium{},
   common.BytesToAddress([]byte{10}): &nativehello{}, 
}

var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{
   common.BytesToAddress([]byte{1}): &ecrecover{},
   common.BytesToAddress([]byte{2}): &sha256hash{},
   common.BytesToAddress([]byte{3}): &ripemd160hash{},
   common.BytesToAddress([]byte{4}): &dataCopy{},
   common.BytesToAddress([]byte{5}): &bigModExp{},
   common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
   common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
   common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
   common.BytesToAddress([]byte{9}): &blake2F{},
   common.BytesToAddress([]byte{10}): &nativehello{}, 
}

type nativehello struct{}

func (c *nativehello) RequiredGas(input []byte) uint64 {
   return 1
}

func (c *nativehello) Run(in []byte) ([]byte, error) {
   out := []byte("Native !!!")
   return out, nil
}

在我的測試合約程式碼中:

pragma solidity ^0.5.0;

contract hello {
   string greeting;

   function bytes32ToStr(bytes32 _bytes32) public pure returns (string) {

   // string memory str = string(_bytes32);
   // TypeError: Explicit type conversion not allowed from "bytes32" to "string storage pointer"
   // thus we should fist convert bytes32 to bytes (to dynamically-sized byte array)

       bytes memory bytesArray = new bytes(32);
       for (uint256 i; i < 32; i++) {
           bytesArray[i] = _bytes32[i];
       }
       return string(bytesArray);
   }

   constructor () public {
      greeting = "hello";
   }

   function say() public  returns (string memory) {
       bytes32 out;
       bytes32 input;
       // bool success = true;
       // assembly {
       //     success := call(20000, 10, 0, input, 32, out, 32)
       // }
       (bool success, bytes memory returnData) = msg.sender.staticcall(abi.encode(3000, 10, input, input.length, out, out.length));
       if (success == true) {
           return string(returnData);
       } else {
           return "failed!";
       }

       //return greeting;
   }
}

在這裡找到了一些例子。

對於上面的例子,hello 合約應該是這樣的:

   function say() public  constant  returns (string memory output) {
       bytes32 out;
       assembly {
           let memPtr := mload(0x20)
           mstore(memPtr, 0x20)
           let success := call(gas, 10, 0x0, memPtr, 0x20, memPtr, 0x20)
           switch success
           case 0 {
               revert(0,0)
           } default {
               out := mload(memPtr)
           }
       }
       output = bytes32ToStr(out);
   }

引用自:https://ethereum.stackexchange.com/questions/78917