首页 文章

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

提问于
浏览
1

我有两个基本 Contract :一个是令牌,第二个是出售 .

Token с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;
    }
}

Sale Contract

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);
    }   
}

StandardTokenOwnable 都是OpenZeppelin存储库的标准实现 . 完整的 Contract 来源here .

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

token.transfer(msg.sender, 1);

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

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

我错过了什么?

1 回答

  • 0

    我使用remix调试了 Contract ,并且抛出了无效的操作码:

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

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

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

    Gas usage: 59137
    

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

相关问题