Verketten von Byte-Strings in Assembly für Anrufeingangsdaten

Ich habe den folgenden Code in meinem Vertrag. Es soll einen Byte-String aufnehmen, der aus einem uint-Flag besteht, dem eine variable Liste von uint-Nummern folgt, und einen Aufruf mit diesen Nummern erstellen. Zum Beispiel für einen Byte-String, der aus dem Flag und nur einer Zahl besteht

0x00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000503b65

er soll bei der eingabe einen anruf an die bereitgestellte vertragsadresse aufbauen

0x912610ab0000000000000000000000000000000000000000000000000000000000503b65

was einen Wert ungleich Null zurückgeben sollte, gefolgt von einem internen Aufruf von handlemit einem Flag von 3. Wenn ich diesen Code jedoch teste, fehlt in der Eingabe, die für den Vertragsaufruf bereitgestellt wird, das erste Argument:

0x912610ab0000000000000000000000000000000000000000000000000000000000000000

Was mache ich falsch? Ist das ein Problem mit dem Stack? Ich leihe mir einen Teil des Codes aus dieser Frage aus, der dieses Problem anscheinend nicht hatte.

function record(bytes script, address contract) public {

    bytes4 sig = bytes4(0x912610ab);
    uint256 flag = uint256At(script, 0);
    uint256 location = 0x20;

    while (location < script.length) {
        uint256 id = uint256At(script, location);
        assembly {
            let x := mload(0x40)
            mstore(x,sig)          
            mstore(add(x,0x04),id) 
            switch call(sub(gas, 5000), contract, 0, x, 0x24, 0, 0)
            case 0 {
                revert(0, 0)
            }
        }
        location += 0x20;
    }

    handle(flag);
}

function uint256At(bytes data, uint256 location) pure internal returns (uint256 result) {
    assembly {
        result := mload(add(data, add(0x20, location)))
    }
}

Antworten (1)

function callByBytes(bytes4 _func, bytes _param) public {
    address _tmpAddr = addr;
    uint paramLen = _param.length;
    uint allLen = 4 + paramLen;
    assembly {
        let p := mload(0x40)
        mstore(p, _func)
        for { let i := 0 } lt(i, paramLen) { i := add(i, 32) } {
            mstore(add(p, add(4,i)), mload(add(add(_param, 0x20), i)))
        }

        let success := call(not(0), _tmpAddr, 0, p, allLen, 0, 0)

        let size := returndatasize
        returndatacopy(p, 0, size)

        switch success
        case 0 {
            revert(p, size)
        }
        default {
            return(p, size)
        }
    }
}