工厂合约生成ERC20代币 钱包导入后初始供应量显示为0
问题说明
编写了用于生成ERC20代币的工厂合约,目前可正常完成代币创建操作,但存在异常:代码中已设置初始供应量参数,将生成的代币地址导入钱包后,代币持有量显示为0,预期初始总供应量应为2000000枚。
相关代码
工厂合约代码片段
contract TokenFactory { event MyTokenCreated(address contractAddress); function createNewMyToken() public returns (address) { MyToken myToken = new MyToken(2000000); emit MyTokenCreated(address(myToken)); return address(myToken); }
MyToken.sol 合约代码
pragma solidity ^0.8.7; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract MyToken is ERC20 { constructor (uint256 initialSupply) ERC20("MyToken", "MY") { _mint(msg.sender, initialSupply * 10 ** 18); } }
问题根因
核心问题出在Solidity的msg.sender取值规则上:当合约内通过new关键字部署新合约时,新合约构造函数中的msg.sender指向的是发起部署操作的合约地址,而非调用工厂合约方法的外部用户地址。
- 调用
TokenFactory.createNewMyToken()方法时,MyToken合约的部署操作由TokenFactory合约发起,因此MyToken构造函数内的msg.sender是TokenFactory合约地址,不是发起交易的个人钱包地址。 - 代码中
_mint(msg.sender, initialSupply * 10 ** 18)逻辑,会将全部2000000枚代币铸造到TokenFactory合约地址下,个人钱包地址在该代币合约中的余额为0。 - 绝大多数钱包导入代币地址后,默认展示的是当前连接钱包地址的对应代币持仓余额,不会主动查询代币的全局总供应量,因此页面显示为0。实际上该代币的链上总供应量是正确的2000000 * 10^18 基础单位,只是全部代币都存放在工厂合约地址中。
修复方式
选择任意一种方案即可:
- 调整代币合约构造函数,新增接收地址参数,部署时直接将代币铸造给调用工厂方法的用户:
// MyToken合约构造函数修改 constructor (uint256 initialSupply, address initialReceiver) ERC20("MyToken", "MY") { _mint(initialReceiver, initialSupply * 10 ** 18); } // 工厂合约部署代币时传入调用者地址 function createNewMyToken() public returns (address) { MyToken myToken = new MyToken(2000000, msg.sender); emit MyTokenCreated(address(myToken)); return address(myToken); }
- 保留现有MyToken代码不变,在工厂合约部署完代币后,调用代币的转账方法,将工厂合约收到的全部初始供应量转给调用者即可。
内容的提问来源于stack exchange,提问作者code_learner93
相关产品推荐
相关产品推荐

