在另一个合同中创建合同实例并调用它的方法会导致抛出异常

时间:2017-09-06 09:53:13

标签: ethereum solidity smartcontracts

我有2个基本合同:一个是令牌,第二个是出售。

令牌êontract

contract MyToken is StandardToken, Ownable {

    string public constant name = "My Sample Token";

    string public constant symbol = "MST";

    uint32 public constant decimals = 18;

    function MyToken(uint _totalSupply) {
       require (_totalSupply > 0);
       totalSupply = _totalSupply;
       balances[msg.sender] = totalSupply;
    }
}

促销合约

contract Sale {
    address owner;

    address public founderAddress;
    uint256 public constant foundersAmount = 50;

    MyToken public token = new MyToken(1000);


    uint256 public issuedTokensAmount = 0;

    function Sale() {
        owner = msg.sender;
        founderAddress = 0x14723a09acff6d2a60dcdf7aa4aff308fddc160c;
        token.transfer(founderAddress, foundersAmount);
    }

    function() external payable {
        token.transfer(msg.sender, 1);
        owner.transfer(msg.value);
    }   
}

StandardToken Ownable 都是OpenZeppelin存储库的标准实现。完整的合同来源here

所以基本上在我的销售合同中,我创建了一个具有固定供应的令牌合同实例,并将所有令牌分配给调用者。然后我将一些令牌转移到创始人地址。当我尝试向销售合同发送一些以太坊时,我试图将我的一些令牌转移到发件人(在Remix浏览器中运行所有代码,我创建一个Sale合约的实例并调用“fallback”方法指定一些以太量)。但是,这会导致“执行期间出现异常。(操作码无效)。请调试事务以获取更多信息。”信息。我在调试时看到的所有内容都是代码在应付方法中失败:

 token.transfer(msg.sender, 1);

我无法确切地看到这个的确切原因,因为我无法进入这种方法并看到内部发生了什么。

有趣的是,当我在Sale Contract构造函数中删除对令牌实例上的传输方法的调用时 - 代码似乎运行正常,没有任何例外。

我错过了什么?

2 个答案:

答案 0 :(得分:0)

我使用remix调试合同,无效的操作码被抛出:

290 DUP8
291 DUP1
292 EXTCODESIZE
293 ISZERO
294 ISZERO
295 PUSH2 012f
298 JUMPI
299 PUSH1 00
301 DUP1
302 INVALID

我遗漏了其余部分,但基本上它加载了令牌合同的地址并调用EXTCODESIZE来检索合同代码大小,并检查它是否不等于0(令牌合同存在),不幸的是,它确实等于0.此时,我不确定这是混音中的限制还是我误解了设置。

我在truffle + testrpc上尝试了相同的合同设置并进行了部署,成功接受了货币。请注意,testrpc指出:

Gas usage: 59137

这意味着它高于默认的sendTransaction w / no data default(21,000 gas)。这意味着在实时环境中,请确保通知用户包含额外的气体,否则由于OOG错误,后备功能可能会失败。

答案 1 :(得分:0)

这背后的原因是您正在使用回退功能。尝试使用正常功能,它应该会发生。