Concatenación de cadenas de bytes en ensamblaje para datos de entrada de llamadas

Tengo el siguiente código en mi contrato. Se supone que debe tomar una cadena de bytes compuesta por un indicador uint seguido de una lista variable de números uint y realizar una llamada usando esos números. Por ejemplo, para una cadena de bytes formada por la bandera y solo un número

0x00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000503b65

se supone que debe construir una llamada a la dirección del contrato proporcionada con la entrada

0x912610ab0000000000000000000000000000000000000000000000000000000000503b65

que debería devolver un valor distinto de cero, seguido de una llamada interna a handlecon un indicador de 3. Sin embargo, cuando pruebo este código, a la entrada que se proporciona a la llamada de contrato le falta el primer argumento:

0x912610ab0000000000000000000000000000000000000000000000000000000000000000

¿Qué estoy haciendo mal? ¿Es esto un problema con la pila? Estoy tomando prestado parte del código de esta pregunta , que no parecía tener este problema.

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)))
    }
}

Respuestas (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)
        }
    }
}