Как восстановить результат, возвращенный вызовом функции другого контракта

Я хочу восстановить результат, возвращенный вызовом функции другого контракта в моем контракте. Мой код прочности ниже, у меня есть

contract A {
    function verifyUser(address userAddress) public returns(bool) {
        bool verified = false;
        uint id = userId[userAddress];
        if (id != 0) {
            verified = true;
        }
        return verified;
    }
}

Я использовал ассемблерный код, чтобы получить возвращаемое значение метода verifyUser контракта A.

 contract B {
function verifAtt(uint idRequiredData, uint P, address userAddress) public returns (bool answer){
    answer=false;
    if(P==1) {
                bytes4 sig = bytes4(keccak256("verifyUser(address)"));
                assembly {
                    // move pointer to free memory spot
                    let ptr := mload(0x40)
                    // put function sig at memory spot
                    mstore(ptr,sig)
                    // append argument after function sig
                    mstore(add(ptr,0x04), userAddress)

                    let result := call(
                      15000, // gas limit
                      sload(dc), // to addr. append var to _slot to access storage variable
                      0, // not transfer any ether
                      ptr, // Inputs are stored at location ptr
                      0x24, // Inputs are 36 bytes long
                      ptr,  //Store output over input
                      0x20) //Outputs are 32 bytes long
                    if eq(result, 0) {
                       revert(0, 0)
                    }
                    answer := mload(ptr) // Assign output to answer var
                    mstore(0x40,add(ptr,0x24)) // Set storage pointer to new space
                }
            }
        }
return answer
}

Я протестировал функцию verifyUser контракта B, и результат всегда верен, даже если результат должен быть ложным. Я хочу быть уверен, что ассемблерный код правильный.

Работаю с ремиксом и солидностью 0.4.16

Ответы (1)

Вам лучше сделать:


verified = A(dc).verifyUser(userAddress);

Не A(dc)создает новый экземпляр. Он приводит dcадрес к Aконтракту.

Вы должны сделать это так, потому что callвернет successвызов, например, закончился ли он на a returnили на revert/assert. Вы можете получить возвращаемые данные, если сделаете call, но для этого потребуется использовать сборку Solidity.


Кроме того, вы должны дважды подумать о том, что вы делаете с файлом for. Это очень опасно. Ваша транзакция не может использовать больше газа, чем лимит газа блока. Поэтому, если ваш массив слишком велик, вызов функции всегда будет завершаться ошибкой.

Как правило, все ваши функции должны выполняться в формате O(1).