文件 1 的 1:ForwarderCloneFactory.sol
pragma solidity >=0.6.0;
library TransferHelper {
function safeApprove(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(
success && (data.length == 0 || abi.decode(data, (bool))),
'TransferHelper::safeApprove: approve failed'
);
}
function safeTransfer(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(
success && (data.length == 0 || abi.decode(data, (bool))),
'TransferHelper::safeTransfer: transfer failed'
);
}
function safeTransferFrom(
address token,
address from,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(
success && (data.length == 0 || abi.decode(data, (bool))),
'TransferHelper::transferFrom: transferFrom failed'
);
}
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, 'TransferHelper::safeTransferETH: ETH transfer failed');
}
}
pragma solidity ^0.8.0;
abstract contract ERC20Interface {
function transfer(address _to, uint256 _value)
public
virtual
returns (bool success);
function balanceOf(address _owner)
public
virtual
view
returns (uint256 balance);
}
pragma solidity ^0.8.19;
contract Forwarder {
address private parentAddress;
address private owner;
event ForwarderDeposited(address from, uint256 value, bytes data);
function initialize(address _owner, address initAddress) public onlyUninitialized {
require(initAddress != address(0), "Invalid parent address");
require(_owner != address(0), "Invalid owner address");
owner = _owner;
parentAddress = initAddress;
}
modifier onlyUninitialized {
require(parentAddress == address(0x0), "Already initialized");
_;
}
modifier onlyOwner {
require(msg.sender == owner, "Only Owner");
_;
}
function getParentAddress() public view onlyOwner returns (address) {
return parentAddress;
}
function getOwner() public view onlyOwner returns (address) {
return owner;
}
fallback() external payable {
flush();
}
receive() external payable {
flush();
}
function setParentAddress(address newAddress) public onlyOwner {
require(newAddress != address(0), "Invalid parent address");
parentAddress = newAddress;
}
function flush() private {
uint256 value = payable(address(this)).balance;
if (value == 0) {
return;
}
(bool success, ) = parentAddress.call{ value: value }("");
require(success, "Flush failed");
emit ForwarderDeposited(msg.sender, value, msg.data);
}
function getERC20Balance(
address tokenContractAddress
) public view returns (uint256) {
ERC20Interface instance = ERC20Interface(tokenContractAddress);
address forwarderAddress = address(this);
uint256 forwarderBalance = instance.balanceOf(forwarderAddress);
if (forwarderBalance == 0) {
return 0;
}
return forwarderBalance;
}
function flushTokens(address tokenContractAddress) external onlyOwner {
ERC20Interface instance = ERC20Interface(tokenContractAddress);
address forwarderAddress = address(this);
uint256 forwarderBalance = instance.balanceOf(forwarderAddress);
if (forwarderBalance == 0) {
return;
}
TransferHelper.safeTransfer(
tokenContractAddress,
parentAddress,
forwarderBalance
);
}
}
pragma solidity ^0.8.0;
library Clones {
function clone(address implementation) internal returns (address instance) {
assembly {
mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
instance := create(0, 0x09, 0x37)
}
require(instance != address(0), "ERC1167: create failed");
}
function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
assembly {
mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
instance := create2(0, 0x09, 0x37, salt)
}
require(instance != address(0), "ERC1167: create2 failed");
}
function predictDeterministicAddress(
address implementation,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
assembly {
let ptr := mload(0x40)
mstore(add(ptr, 0x38), deployer)
mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff)
mstore(add(ptr, 0x14), implementation)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73)
mstore(add(ptr, 0x58), salt)
mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37))
predicted := keccak256(add(ptr, 0x43), 0x55)
}
}
function predictDeterministicAddress(address implementation, bytes32 salt)
internal
view
returns (address predicted)
{
return predictDeterministicAddress(implementation, salt, address(this));
}
}
pragma solidity ^0.8.19;
contract ForwarderCloneFactory {
address immutable public forwarderImplementation;
event ForwardersDeployed(address[] addresses);
constructor() {
forwarderImplementation = address(new Forwarder());
}
function createForwarders(address parent, uint8 numForwarders) external {
address[] memory forwarders = new address[](numForwarders);
for (uint8 i = 0; i < numForwarders; i++) {
address clone = Clones.clone(forwarderImplementation);
Forwarder(payable(clone)).initialize(msg.sender, parent);
forwarders[i] = clone;
}
emit ForwardersDeployed(forwarders);
}
}