String in mehrere Variablen parsen

Ich mache Oraclize-Aufrufe auf dem Json-RPC einer Kette, um diese Funktion zu erhalten:

  function getTransfer(uint _transferId) public view returns(uint,address,uint){
    Details memory _locked = transferDetails[_transferId];
    return(_locked.amount,_locked.owner,_locked.transferId);
  }

Es ist wirklich nicht so wichtig, was es tut, aber wenn ich diese Funktion von oraclize aus aufrufe, bekomme ich eine Zeichenfolge mit allen drei Variablen zurück ... zum Beispiel:

"0x0000000000000000000000000000000000000000000000000b1a2bc2ec500000000000000000000000000000c69c64c226fea62234afe4f5832a051ebc8605400000000000000000000000000000000000000000000000000000000000000001"

Ich arbeite an einem Rückruf, um dies in eine uint, eine Adresse und eine uint zu zerlegen. Das ist, was ich bisher habe:

function __callback(string result) public returns(uint,address,uint){
    emit Print(result);
    string memory _int = Strings.substring(result,60,90);
    emit Print(_int);
    emit P2(stringToUint(_int));
    uint _amount= parseInt(_int);
    _int =strConcat('0x',Strings.substring(result,91,130)) ;
    address _owner =  parseAddr(_int);
    _int =Strings.substring(result,131,194) ;
    uint _transId = parseInt(_int);
    return (_amount,_transId,_transId);
}

Diese Art von Arbeit, aber das Problem ist, dass die uints tatsächlich im Hex-Wert sind (diese Zeichenfolge sollte .8e18,0x,1 zurückgeben), aber ich muss eine Literalzeichenfolge in eine Hexadezimalzahl umwandeln ... wenn Sie welche haben Ideen. Kann ich auch eine Teilzeichenfolge verwenden oder ändert sich die Länge meiner Zeichenfolge mit den Werten?

Der Code des Vertrags, den wir aufrufen, ist hier: https://ropsten.etherscan.io/address/0xd29d27cfacf7b77a16edac7c2cddf07dc4a603b8#readContract

ps Es kann den Remix brechen, wenn man diese Art von String-Manipulation macht

Antworten (1)

Dieser Code funktioniert, wenn jemand anderes neugierig ist. Musste eine Zeichenfolge uint hex in uint-Konverter schreiben:

  pragma solidity ^0.4.21;



/**
 * Set of utilities to parse results of JSON-RPC call from oraclize.
 */
contract HexUtils {

    //constants for comparison and conversions below
    byte constant a = byte('a');
    byte constant f = byte('f');
    byte constant A = byte('A');
    byte constant F = byte('F');
    byte constant zero = byte('0');
    byte constant nine = byte('9');

    /**
     * Convert a character to its hex value as a byte. This is NOT
     * very efficient but is a brute-force way of getting the job done.
     * It's possible to optimize this with assembly in solidity but
     * that would require a lot more time.
     */
    function hexCharToByte(uint c) pure internal returns(uint) {
        byte b = byte(c);

        //convert ascii char to hex value
        if(b >= zero && b <= nine) {
            return c - uint(zero);
        } else if(b >= a && b <= f) {
            return 10 + (c - uint(a));
        } else if(b >= A && b <= F) {
            return 10 + (c - uint(A));
        }
    }

    /**
     * Check whether a string has hex prefix.
     */
    function hasZeroXPrefix(string s) pure internal returns(bool) {
        bytes memory b = bytes(s);
        if(b.length < 2) {
            return false;
        }
        return b[1] == 'x';
    }

    /**
     * Convert a hex string to a uint. This is NOT very efficient but
     * gets the job done. Could probably optimize with assembly but would
     * require a lot more time.
     */
    function hexToUint(string s) pure public returns(uint) {
        //convert string to bytes
        bytes memory b = bytes(s);

        //make sure zero-padded
        require(b.length % 2 == 0, "String must have an even number of characters");

        //starting index to parse from
        uint i = 0;
        //strip 0x if present
        if(hasZeroXPrefix(s)) {
            i = 2;
        }
        uint r = 0;
        for(;i<b.length;i++) {
            //convert each ascii char in string to its hex/byte value.
            uint b1 = hexCharToByte(uint(b[i]));

            //shift over a nibble for each char since hex has 2 chars per byte
            //OR the result to fill in lower 4 bits with hex byte value.
            r = (r << 4) | b1;
        }
        //result is hex-shifted value of all bytes in input string.
        return r;
    }

    /**
     * Extract a substring from an input string.
     */
    function substr(string s, uint start, uint end) pure public returns(string) {
        require(end > start, "End must be more than start");
        bytes memory res = new bytes(end-start);
        bytes memory bts = bytes(s);
        require(end <= bts.length, "End must be less than or equal to the length of string");
        require(start >= 0 && start < bts.length, "Start must be between 0 and length of string");

        uint idx = 0;
        for(uint i=start;i<end;++i) {
          //just copy bytes over
            res[idx] = bts[i];
            ++idx;
        }
        return string(res);
    }

    /**
     * Parse a hex string into an address.
     */
    function parseAddr(string _a) internal pure returns (address){
        //address is really a uint160...
        uint iaddr = hexToUint(_a);
        return address(iaddr);
    }

    /**
     * Parse oraclize result into uint, address, uint values.
     */
    function parseResults(string _hexData) pure public returns(uint, address, uint) {
        //start at zero or 2 depending on 0x prefix in string
        uint startIdx = 0;
        if(hasZeroXPrefix(_hexData)) {
            startIdx = 2;
        }
        bytes memory bts = bytes(_hexData);
        //take the first 64 bytes and convert to uint
        uint ethVal = hexToUint(substr(_hexData, startIdx,64+startIdx));

        //id is at the end and will be 64 bytes. So grab its starting idx first.
        uint idStart = bts.length - 64;

        //the address portion will end where the id starts.
        uint addrEnd = idStart-1;

        //parse the last 40 bytes of the address hex.
        address addr = parseAddr(substr(_hexData, addrEnd-40, addrEnd));

        //then extract the id
        uint id = hexToUint(substr(_hexData, idStart, bts.length));

        //done
        return (ethVal, addr, id);
    }
}