0

The thing is I want to create my own custom precompiled contracts, and use it in my private chain of ethereum.

Here is my code, but it is not right when I call hello.say() in geth attach line.

In geth side, I changed core/vm/contracts.go file, add my custom contracts.

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
}

And in my test contract code:

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;
    }
}
0

Found some examples here.

And for the above example, the hello contract should be something like:

    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);
    }
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.