Я хочу восстановить результат, возвращенный вызовом функции другого контракта в моем контракте. Мой код прочности ниже, у меня есть
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
Вам лучше сделать:
verified = A(dc).verifyUser(userAddress);
Не A(dc)
создает новый экземпляр. Он приводит dc
адрес к A
контракту.
Вы должны сделать это так, потому что call
вернет success
вызов, например, закончился ли он на a return
или на revert/assert
. Вы можете получить возвращаемые данные, если сделаете call
, но для этого потребуется использовать сборку Solidity.
Кроме того, вы должны дважды подумать о том, что вы делаете с файлом for
. Это очень опасно. Ваша транзакция не может использовать больше газа, чем лимит газа блока. Поэтому, если ваш массив слишком велик, вызов функции всегда будет завершаться ошибкой.
Как правило, все ваши функции должны выполняться в формате O(1)
.