我需要进行递归evm消息调用。根据我对稳定性工作原理的理解,同一合约内的调用不会触发evm消息。但是对于我的用例,我希望每个递归调用都是evm消息调用。这是一个斐波那契契约。以下是正常版本
contract Fibonacci {
function fibonacci(uint32 n) public pure returns(uint32) {
if (n == 0 || n == 1) {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
在上面的例子中,fibonacci
的递归调用不会触发evm链调用,因为它们发生在同一个合约中。要从一个智能合约中调用另一个智能合约的代码,你需要你想调用的合约的地址。因此,我使用相同的想法来强制evm递归链调用(至少我是这样认为的)。下面是实现
contract Fibonacci {
function fibonacciIndirect(uint32 n) public view returns(uint32) {
if (n == 0 || n == 1) {
return n;
}
uint32 n1;
uint32 n2;
n1 = Fibonacci(this).fibonacciIndirect(n - 1);
n2 = Fibonacci(this).fibonacciIndirect(n - 2);
return n1 + n2;
}
}
所以我使用this
作为斐波那契合约的地址,并使用它来触发evm链调用。我的测试表明,该函数正确地计算斐波那契序列的第n个值,并且与正常版本相比消耗更多的气体,但因为我没有在文档中看到这一点,所以我不确定这是否是正确的方法。是的,我知道更多的evm调用意味着更多的gas,没有人会因为这个原因而选择fibonacci的第二个实现。但是作为测试的一部分,我需要能够强制递归evm消息调用。
可以强制使用"外部调用";(即调用而不是跳转)到功能foo
在固体通过调用你的功能使用this.foo()
。这在这里的文档中有详细说明。这是您在第二个示例中使用的。当然,您不应该在生产环境中使用它,或者只有当您有很好的理由这样做时才应该这样做。