在Solidity中实现代币买卖及ETH兑换代币功能的开发咨询
实现ETH兑换代币功能的完整合约代码
你需要在原有ERC20合约基础上新增汇率配置、收款自动兑换逻辑、权限控制和提现功能,以下是适配Solidity 0.4.22版本的完整可运行代码:
pragma solidity 0.4.22; library SafeMath { function sub(uint256 a, uint256 b) internal pure returns (uint256) { assert(b <= a); return a - b; } function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; assert(c >= a); return c; } } contract ERC20Basic { string public constant name = "Community Token"; string public constant symbol = "COMM"; uint8 public constant decimals = 1; event Approval(address indexed tokenOwner, address indexed spender, uint tokens); event Transfer(address indexed from, address indexed to, uint tokens); // 新增兑换成功事件 event TokensPurchased(address indexed buyer, uint256 ethAmount, uint256 tokenAmount); mapping(address => uint256) balances; mapping(address => mapping (address => uint256)) allowed; uint256 totalSupply_; using SafeMath for uint256; // 新增:合约所有者地址 address public owner; // 新增:ETH兑换代币汇率,示例为1ETH兑换1000枚COMM,可自行调整 uint256 public constant ETH_TO_TOKEN_RATE = 1000; // 新增:仅所有者可调用的修饰符 modifier onlyOwner() { require(msg.sender == owner); _; } constructor(uint256 total) public { totalSupply_ = total; balances[msg.sender] = totalSupply_; owner = msg.sender; } // 新增:用户直接向合约转ETH时自动触发兑换的fallback函数 function () payable public { buyTokens(); } // 新增:主动调用兑换代币函数 function buyTokens() public payable { // 检查用户转入的ETH大于0 require(msg.value > 0); // 计算可兑换的代币数量 uint256 tokenAmount = msg.value.mul(ETH_TO_TOKEN_RATE).div(1 ether); // 检查合约有足够的代币可以兑付 require(balances[address(this)] >= tokenAmount); // 从合约地址向用户转代币 balances[address(this)] = balances[address(this)].sub(tokenAmount); balances[msg.sender] = balances[msg.sender].add(tokenAmount); emit Transfer(address(this), msg.sender, tokenAmount); emit TokensPurchased(msg.sender, msg.value, tokenAmount); } // 新增:所有者提取合约内的ETH function withdrawETH() public onlyOwner { owner.transfer(address(this).balance); } // 新增:所有者提取合约内剩余的COMM代币 function withdrawRemainingTokens() public onlyOwner { uint256 remaining = balances[address(this)]; require(remaining > 0); balances[address(this)] = balances[address(this)].sub(remaining); balances[owner] = balances[owner].add(remaining); emit Transfer(address(this), owner, remaining); } function totalSupply() public view returns (uint256) { return totalSupply_; } function balanceOf(address tokenOwner) public view returns (uint) { return balances[tokenOwner]; } function transfer(address receiver, uint numTokens) public returns (bool) { require(numTokens <= balances[msg.sender]); balances[msg.sender] = balances[msg.sender].sub(numTokens); balances[receiver] = balances[receiver].add(numTokens); emit Transfer(msg.sender, receiver, numTokens); return true; } function approve(address delegate, uint numTokens) public returns (bool) { allowed[msg.sender][delegate] = numTokens; emit Approval(msg.sender, delegate, numTokens); return true; } function allowance(address owner, address delegate) public view returns (uint) { return allowed[owner][delegate]; } function transferFrom(address owner, address buyer, uint numTokens) public returns (bool) { require(numTokens <= balances[owner]); require(numTokens <= allowed[owner][msg.sender]); balances[owner] = balances[owner].sub(numTokens); allowed[owner][msg.sender] = allowed[owner][msg.sender].sub(numTokens); balances[buyer] = balances[buyer].add(numTokens); emit Transfer(owner, buyer, numTokens); return true; } }
功能说明
- 兑换逻辑支持两种使用方式:用户直接向合约地址转账ETH自动兑换,或者主动调用
buyTokens方法完成兑换,两种方式都会按照预设汇率自动计算到账的代币数量 - 汇率参数
ETH_TO_TOKEN_RATE可自行调整,示例值1000对应1ETH兑换1000枚COMM,如需调整直接修改该常量的数值即可 - 新增了
TokensPurchased事件,可用于链上查询兑换记录,方便做数据统计 - 所有兑换逻辑都使用了原有的SafeMath库做运算,避免溢出问题
注意:合约部署完成后,需要先从部署者地址向合约地址转入足够的COMM代币,否则用户兑换时会因为合约代币余额不足触发交易回滚。如果后续需要调整兑换规则,可基于当前逻辑扩展汇率修改、兑换限额等功能。
内容的提问来源于stack exchange,提问作者Nalks_
相关产品推荐
相关产品推荐

