如何创建提现功能

huangapple go评论46阅读模式
英文:

How to create a withdraw function

问题

以下是代码部分的翻译:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

contract CrowdFunding {
    event testConditon(
        uint256 deadline,
        uint256 currentTimeInMs,
        uint256 diff,
        bool condition
    );

    struct Campaign {
        address payable owner;
        string title;
        string description;
        uint256 target;
        uint256 deadline;
        uint256 amountCollected;
        string image;
        address[] donators;
        uint256[] donations;
    }

    mapping(uint256 => Campaign) public campaigns;

    uint256 public numberOfCampaigns = 0;

    function createCampaign(
        address _owner,
        string memory _title,
        string memory _description,
        uint256 _target,
        uint256 _deadline,
        string memory _image
    ) public returns (uint256) {
        Campaign storage campaign = campaigns[numberOfCampaigns];
        uint256 currentTimeInMs = block.timestamp * 1000;

        emit testConditon(
            _deadline,
            currentTimeInMs,
            _deadline - currentTimeInMs,
            _deadline > currentTimeInMs
        );

        require(
            _deadline > currentTimeInMs,
            "截止日期必须在未来"
        );

        campaign.owner = payable(_owner);
        campaign.title = _title;
        campaign.description = _description;
        campaign.target = _target;
        campaign.deadline = _deadline;
        campaign.image = _image;
        campaign.amountCollected = 0;

        numberOfCampaigns++;

        return numberOfCampaigns - 1;
    }

    function donateToCampaign(uint256 _id) public payable {
        uint256 amount = msg.value;

        Campaign storage campaign = campaigns[_id];

        campaign.donators.push(msg.sender);
        campaign.donations.push(amount);

        (bool sent, ) = payable(campaign.owner).call{value: amount}("");

        
        if (sent) {
            campaign.amountCollected += amount;
        }
    }

    function getDonators(uint256 _id)
        public
        view
        returns (address[] memory, uint256[] memory)
    {
        return (campaigns[_id].donators, campaigns[_id].donations);
    }

    function getCampaigns() public view returns (Campaign[] memory) {
        Campaign[] memory allCampaigns = new Campaign[](numberOfCampaigns);

        for (uint256 i = 0; i < numberOfCampaigns; i++) {
            Campaign storage item = campaigns[i];
            allCampaigns[i] = item;
        }

        return allCampaigns;
    }

    function withdraw(uint256 _id) public {
        Campaign storage campaign = campaigns[_id];

        require(
            campaign.amountCollected >= campaign.target,
            "该筹款活动尚未达到目标"
        );

        //截止日期已过期
        // require(
        //     campaign.deadline < block.timestamp * 1000,
        //     "截止日期尚未过期"
        // );

        require(
            campaign.owner == msg.sender,
            "只有筹款活动的所有者可以提取资金"
        );

        campaign.owner.transfer(campaign.amountCollected);
        campaign.amountCollected = 0;
    }
}

希望这能帮助您解决问题。

英文:

I created a basic contract for crowdfunding. But cannot figure out how to create a withdraw function.

Withdraw function will transfer a campaign's collected funds to the campaign's owner. This is my full crowdfunding contract:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

contract CrowdFunding {
    event testConditon(
        uint256 deadline,
        uint256 currentTimeInMs,
        uint256 diff,
        bool condition
    );

    struct Campaign {
        address payable owner;
        string title;
        string description;
        uint256 target;
        uint256 deadline;
        uint256 amountCollected;
        string image;
        address[] donators;
        uint256[] donations;
    }

    mapping(uint256 =&gt; Campaign) public campaigns;

    uint256 public numberOfCampaigns = 0;

    function createCampaign(
        address _owner,
        string memory _title,
        string memory _description,
        uint256 _target,
        uint256 _deadline,
        string memory _image
    ) public returns (uint256) {
        Campaign storage campaign = campaigns[numberOfCampaigns];
        uint256 currentTimeInMs = block.timestamp * 1000;

        emit testConditon(
            _deadline,
            currentTimeInMs,
            _deadline - currentTimeInMs,
            _deadline &gt; currentTimeInMs
        );

        require(
            _deadline &gt; currentTimeInMs,
            &quot;The deadline must be in the future&quot;
        );

        campaign.owner = payable(_owner);
        campaign.title = _title;
        campaign.description = _description;
        campaign.target = _target;
        campaign.deadline = _deadline;
        campaign.image = _image;
        campaign.amountCollected = 0;

        numberOfCampaigns++;

        return numberOfCampaigns - 1;
    }

    function donateToCampaign(uint256 _id) public payable {
        uint256 amount = msg.value;

        Campaign storage campaign = campaigns[_id];

        campaign.donators.push(msg.sender);
        campaign.donations.push(amount);

        (bool sent, ) = payable(campaign.owner).call{value: amount}(&quot;&quot;);

        if (sent) {
            campaign.amountCollected += amount;
        }
    }

    function getDonators(uint256 _id)
        public
        view
        returns (address[] memory, uint256[] memory)
    {
        return (campaigns[_id].donators, campaigns[_id].donations);
    }

    function getCampaigns() public view returns (Campaign[] memory) {
        Campaign[] memory allCampaigns = new Campaign[](numberOfCampaigns);

        for (uint256 i = 0; i &lt; numberOfCampaigns; i++) {
            Campaign storage item = campaigns[i];
            allCampaigns[i] = item;
        }

        return allCampaigns;
    }

    function withdraw(uint256 _id) public {
        Campaign storage campaign = campaigns[_id];

        require(
            campaign.amountCollected &gt;= campaign.target,
            &quot;The campaign has not reached its target&quot;
        );

        //deadline has passed
        // require(
        //     campaign.deadline &lt; block.timestamp * 1000,
        //     &quot;The deadline has not passed yet&quot;
        // );

        require(
            campaign.owner == msg.sender,
            &quot;Only the owner of the campaign can withdraw the funds&quot;
        );

        campaign.owner.transfer(campaign.amountCollected);
        campaign.amountCollected = 0;
    }
}

I have no idea how to solve this issue.

答案1

得分: 0

似乎你缺少了payable关键字来触发代币转账。尝试这样做:

function withdraw(uint256 _id) public {
Campaign storage campaign = campaigns[_id];
(bool success, ) = payable(campaign.owner).call{value: campaign.amountCollected}("");
require(success, "Withdrawal failure");
campaign.amountCollected = 0;
}

警告:这个函数以及你的函数存在重入漏洞。

英文:

Looks like you are missing the payable keyword to trigger the token transfer. Try this:

function withdraw(uint256 _id) public {
Campaign storage campaign = campaigns[_id];
(bool success, ) = payable(campaign.owner).call{value: campaign.amountCollected}(&quot;&quot;);
require(success, &quot;Withdrawal failure&quot;);
campaign.amountCollected = 0;
}

Warning: this function and your function are having a reentrency vulnerability.

huangapple
  • 本文由 发表于 2023年2月14日 19:00:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/75446871.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定