I am specifically interested in calling a function whose return-type is unknown to me.
More precisely:
- The contract which owns the function has had several versions over time
- My contract may call this function on any of the instances deployed to the network
- The function's return-type is
(uint256)
some cases and(uint256, uint256)
in other cases
I've figured that I can call the function without storing its returned-value, so compilation by itself will not be a problem. Then, assuming that the actual values are still on the stack (is this assumption possibly wrong, due to compiler optimization or other reasons?), I can read the two topmost slots in the stack and continue as planned from that point.
Alternatively, I thought I could declare an interface of the contract in doubt, with the function in doubt returning (uint256, uint256)
, and then use that interface in order to call the function.
However, I tried it, and the function which returns a single uint256
has reverted:
pragma solidity 0.4.25;
contract NotMyContract1 {
uint256 a = 1;
function func() external view returns (uint256) {
return a;
}
}
contract NotMyContract2 {
uint256 a = 1;
uint256 b = 2;
function func() external view returns (uint256, uint256) {
return (a, b);
}
}
interface INotMyContract {
function func() external view returns (uint256, uint256);
}
contract MyContract {
INotMyContract private notMyContract;
constructor(INotMyContract _notMyContract) public {
notMyContract = _notMyContract;
}
function test() public view returns (uint256, uint256) {
return notMyContract.func();
}
}
contract("MyContract", function(accounts) {
it("", async function() {
await test("1");
await test("2");
});
async function test(id) {
const notMyContract = await artifacts.require("NotMyContract" + id).new();
const myContract = await artifacts.require("MyContract").new(notMyContract.address);
try {
const [a, b] = await myContract.test();
console.log(id, a.toString(), b.toString());
}
catch (error) {
console.log(id, error.message);
}
}
});
So I would be happy to hear any idea on how to do this in assembly, as well as any alternative suggestions.
The assembly operations which I had in mind are dup1 … dup16
and swap1 … swap16
.
Thank you!