代码之家  ›  专栏  ›  技术社区  ›  Justin

是否可以获取从另一个契约外部函数获取数据的外部函数的返回值?

  •  1
  • Justin  · 技术社区  · 7 年前

    注: 这只是从web3js调用外部视图函数时的问题,因为它不会创建事务


    我有两份合同, A B
    (一个是存储合同,另一个更像是逻辑合同)

    如果 一个 具有如下功能:

    function getValueFor(uint8 index) external view returns(uint8) {
        return someMapping[index];
    }
    

    以及 具有如下功能:

    function isValid() external view returns(bool) {
        return instanceOfA.getValueFor(1) == 1;
    }
    

    来自Mist或web3js的返回值 一个 按预期工作,并在调用 总是返回默认值。
    (在这种情况下 0 )

    您不能从web3js的contract->contract外部/常量函数调用中获取返回值吗?这需要交易吗?

    更新

    answer 在以太坊堆叠交换上。

    在交易过程中,我对这项工作基本上是不正确的。它似乎在处理我的特定测试函数,尽管大多数其他函数都失败了 (我刚用了一个测试函数,运气不好) .

    问题的根源在于没有在我的Geth节点上启用新的拜占庭 (支持新的EVM功能) .

    2 回复  |  直到 7 年前
        1
  •  0
  •   Adam Kipnis    7 年前

    你当然可以。快速运行松露控制台将显示:

    pragma solidity >0.4.23 <0.5.0;
    
    contract A {
        uint256 value;
    
        constructor(uint256 v) public {
            value = v;
        }
    
        function getValue() external view returns (uint256) {
            return value;
        }
    }
    
    contract B {
        A other;
    
        constructor(address a) public {
            other = A(a);
        }
    
        function getValueFromA() external view returns (uint256) {
            return other.getValue();
        }
    }
    

    执行:

    $ truffle console
    truffle(development)> var aContract = web3.eth.contract([{"constant":true,"inputs":[],"name":"getValue","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"v","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]);
    
    truffle(development)> var transObj = { from: web3.eth.accounts[0], data: '0x608060405234801561001057600080fd5b506040516020806100ea83398101806040528101908080519060200190929190505050806000819055505060a1806100496000396000f300608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806320965255146044575b600080fd5b348015604f57600080fd5b506056606c565b6040518082815260200191505060405180910390f35b600080549050905600a165627a7a72305820dd332a08d090a6766cf7c2e86f41abc58a31e4d1afe7cb635a0a1b755a9b81cd0029', gas: '4700000'};
    
    truffle(development)> var a = aContract.new(35, transObj);
    
    truffle(development)> a.getValue();
    BigNumber { s: 1, e: 1, c: [ 35 ] }
    
    truffle(development)> var bContract = web3.eth.contract([{"constant":true,"inputs":[],"name":"getValueFromA","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"a","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]);
    
    truffle(development)> transObj.data = '0x608060405234801561001057600080fd5b506040516020806101e783398101806040528101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610164806100836000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680639b9be7cd14610046575b600080fd5b34801561005257600080fd5b5061005b610071565b6040518082815260200191505060405180910390f35b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663209652556040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1580156100f857600080fd5b505af115801561010c573d6000803e3d6000fd5b505050506040513d602081101561012257600080fd5b81019080805190602001909291905050509050905600a165627a7a7230582096cc7381535016229911569ae3821103afb9a1ce582f3fc7bf226f3b5fac72380029';
    
    truffle(development)> b = bContract.new(a.address, transObj);
    
    truffle(development)> b.getValueFromA();
    BigNumber { s: 1, e: 1, c: [ 35 ] }
    
        2
  •  0
  •   Justin    7 年前

    这里有一个解决方法/黑客,它可以在事务之外处理这个问题 (外部视图函数调用使用 web3js )

    pragma solidity >0.4.23 <0.5.0;
    
    contract Parent {
        int value;
    
        function setValue(int v) public {
            value = v;
        }
    
        function getValue() external view returns (int) {
            return value;
        }
    }
    
    contract Child {
        Parent parent;
    
        function setParent(address a) public {
            parent = Parent(a);
        }
    
        function getValue() external view returns (int value) {
            // -- Should work
            //return parent.getValue();
    
            // -- Make it work
            address addr = address(parent);
            bytes4 sig = bytes4(keccak256("getValue()"));
    
            assembly {
               let o := mload(0x40) // Empty storage pointer
               mstore(o,sig)        // Push function signature to memory (function signature is 4 bytes/0x04)
    
               let success := call(
                   15000,           // Gas limit
                   addr,            // To address
                   0,               // No ether to transfer
                   o,               // Input location ptr
                   0x04,            // Input size (0)
                   o,               // Store oputput over input
                   0x20)            // Output size (32 bytes)
    
               value := mload(o)
               mstore(0x40,add(o,0x04))
            }
        }
    }
    

    这不只是使用常规函数调用就可以工作,这看起来还是很愚蠢的。
    (也许这是个虫子?)

    推荐文章