【问题标题】:Transaction is getting reverted in the `refundToInsurer()` function call交易在 refundToInsurer() 函数调用中恢复
【发布时间】:2023-02-03 14:17:30
【问题描述】:

InsuranceProvider 的部署工作正常,使用所需参数调用 newContract() 成功创建/部署 InsuranceConsumer 合约。甚至,payOutContract() 在将 ETH 余额从 InsuranceConsumer 转移到客户的钱包。

问题出在 refundToInsurer() 函数上,因为它应该将 ETH 余额从 InsuranceConsumer 转移到保险公司的钱包,但它的交易失败/恢复。

这是代码:

SPDX-License-Identifier: MIT

pragma solidity ^0.8.7;

import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";

contract InsuranceProvider {
    address payable public insurer;
    AggregatorV3Interface internal priceFeed;

    modifier onlyOwner() {
        require(insurer == msg.sender, "Only Insurance provider can do this");
        _;
    }

    constructor() payable {
        priceFeed = AggregatorV3Interface(
            0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e
        );
        insurer = payable(msg.sender);
    }

    function newContract(
        address payable _client,
        uint256 _premium,
        uint256 _payoutValue
    ) public payable onlyOwner returns (address) {
        //create contract, send payout amount so contract is fully funded plus a small buffer
        InsuranceConsumer i = (new InsuranceConsumer){
            value: ((_payoutValue * 1 ether) / (uint256(getLatestPrice())))
        }(_client, _premium, _payoutValue);

        return address(i);
    }

    function getLatestPrice() public view returns (int256) {
        (, int256 price, , uint256 timeStamp, ) = priceFeed.latestRoundData();
        // If the round is not complete yet, timestamp is 0
        require(timeStamp > 0, "Round not complete");
        return price;
    }

    function payOutContract(address _contract) public {
        InsuranceConsumer i = InsuranceConsumer(_contract);
        // Transfer agreed amount to client
        i.payOutContract();
    }

    function refundToInsurer(address _contract) public onlyOwner  {
        InsuranceConsumer i = InsuranceConsumer(_contract);
        // Transfer back the amount to insurer 
        i.refundToInsurer();
   }
}

contract InsuranceConsumer {
    AggregatorV3Interface internal priceFeed;
    address payable public insurer;
    address payable client;
    uint256 startDate;
    uint256 premium;
    uint256 payoutValue;

    constructor(
        address payable _client,
        uint256 _premium,
        uint256 _payoutValue
    ) payable {
        //set ETH/USD Price Feed
        priceFeed = AggregatorV3Interface(
            0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e
        );

        //first ensure insurer has fully funded the contract
        require(
            msg.value >= _payoutValue / uint256(getLatestPrice()),
            "Not enough funds sent to contract"
        );

        //now initialize values for the contract
        insurer = payable(msg.sender);
        client = _client;
        startDate = block.timestamp; //contract will be effective immediately on creation
        premium = _premium;
        payoutValue = _payoutValue;
    }

    function payOutContract() public {
        //Transfer agreed amount to client
        client.transfer(address(this).balance);
    }

    function refundToInsurer() public {
        // Transfer back the amount to insurer
        insurer.transfer(address(this).balance);
    }

    function getLatestPrice() public view returns (int256) {
        (, int256 price, , uint256 timeStamp, ) = priceFeed.latestRoundData();
        // If the round is not complete yet, timestamp is 0
        require(timeStamp > 0, "Round not complete");
        return price;
    }
}

任何人都可以指出我在refundToInsurer() 函数中犯的逻辑错误吗?

【问题讨论】:

  • 你在goerli网络吗?
  • 是的,@Yilmaz。我已经解决了这个问题。您可以检查解决方案。

标签: ethereum solidity smartcontracts transfer brownie


【解决方案1】:

因为,我们正在使用 InsuranceProvidernewContract() 函数创建 InsuranceConsumer。因此,InsuranceConsumermsg.sender 将成为 InsuranceProvider 本身,而不是保险公司的钱包。

因此,当我们通过 InsuranceProvider 调用 InsuranceConsumerrefundInsurer() 时,它会执行以下操作:

insurer.transfer(address(this).balance);

这意味着将InsuranceConsumer中可用的ETH转移到InsuranceProvider(不是保险公司的钱包),并且由于InsuranceProvider预计不会是receiver,这就是它恢复交易的原因。

因此,更正后的代码将是:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.7;

import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";

contract InsuranceProvider {
    address payable public insurer;
    AggregatorV3Interface internal priceFeed;

    modifier onlyOwner() {
        require(insurer == msg.sender, "Only Insurance provider can do this");
        _;
    }

    constructor() payable {
        priceFeed = AggregatorV3Interface(
            0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e
        );
        insurer = payable(msg.sender);
    }

    function newContract(
        address payable _client,
        uint256 _premium,
        uint256 _payoutValue
    ) public payable onlyOwner returns (address) {
        //create contract, send payout amount so contract is fully funded plus a small buffer
        InsuranceConsumer i = (new InsuranceConsumer){
            value: ((_payoutValue * 1 ether) / (uint256(getLatestPrice())))
        }(_client, _premium, _payoutValue);

        return address(i);
    }

    function getLatestPrice() public view returns (int256) {
        (, int256 price, , uint256 timeStamp, ) = priceFeed.latestRoundData();
        // If the round is not complete yet, timestamp is 0
        require(timeStamp > 0, "Round not complete");
        return price;
    }

    function payOutContract(address _contract) public onlyOwner {
        // Transfer agreed amount to client
        InsuranceConsumer i = InsuranceConsumer(_contract);
        i.payOutContract();
    }

    function refundToInsurer(address _contract) public onlyOwner {
        // Transfer back the amount to insurer 
        InsuranceConsumer i = InsuranceConsumer(_contract);
        i.refundToInsurer(insurer);
   }
}

contract InsuranceConsumer {
    AggregatorV3Interface internal priceFeed;
    address payable public insurer;
    address payable client;
    uint256 startDate;
    uint256 premium;
    uint256 payoutValue;

    constructor(
        address payable _client,
        uint256 _premium,
        uint256 _payoutValue
    ) payable {
        //set ETH/USD Price Feed
        priceFeed = AggregatorV3Interface(
            0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e
        );

        //first ensure insurer has fully funded the contract
        require(
            msg.value >= _payoutValue / uint256(getLatestPrice()),
            "Not enough funds sent to contract"
        );

        //now initialize values for the contract
        insurer = payable(msg.sender);
        client = _client;
        startDate = block.timestamp; //contract will be effective immediately on creation
        premium = _premium;
        payoutValue = _payoutValue;
    }

    function payOutContract() public {
        //Transfer agreed amount to client
        client.transfer(address(this).balance);
    }

    function refundToInsurer(address payable _insurer) public {
        // Transfer back the amount to insurer 
        _insurer.transfer(address(this).balance);
   }

    function getLatestPrice() public view returns (int256) {
        (, int256 price, , uint256 timeStamp, ) = priceFeed.latestRoundData();
        // If the round is not complete yet, timestamp is 0
        require(timeStamp > 0, "Round not complete");
        return price;
    }
}

现在,在调用 refundInsurer() 时,我们明确将保险公司作为参数传递,它从 InsuranceProvider 中获取 msg.sender 的值,因此 msg.sender 将成为保险公司的在这种情况下,钱包(部署InsuranceProvider)。

现在,当我们通过InsuranceProvider 调用InsuranceConsumerrefundInsurer() 时,它正在执行:

_insurer.transfer(address(this).balance);

意思是将InsuranceConsumer中可用的ETH转入保险公司的钱包。因此,交易将成功导致资金从InsuranceConsumer提取到保险公司的钱包。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多