Solidity
有沒有使用預編譯合約的例子?
問題是我想創建自己的自定義預編譯合約,並在我的私有乙太坊鏈中使用它。
這是我的程式碼,但是當我呼叫
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); }