文件 1 的 5:CloneFactory.sol
pragma solidity 0.7.5;
contract CloneFactory {
function createClone(address target, bytes32 salt)
internal
returns (address payable result)
{
bytes20 targetBytes = bytes20(target);
assembly {
let clone := mload(0x40)
mstore(
clone,
0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000
)
mstore(add(clone, 0x14), targetBytes)
mstore(
add(clone, 0x28),
0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
)
result := create2(0, clone, 0x37, salt)
}
}
function isClone(address target, address query)
internal
view
returns (bool result)
{
bytes20 targetBytes = bytes20(target);
assembly {
let clone := mload(0x40)
mstore(
clone,
0x363d3d373d3d3d363d7300000000000000000000000000000000000000000000
)
mstore(add(clone, 0xa), targetBytes)
mstore(
add(clone, 0x1e),
0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
)
let other := add(clone, 0x40)
extcodecopy(query, other, 0, 0x2d)
result := and(
eq(mload(clone), mload(other)),
eq(mload(add(clone, 0xd)), mload(add(other, 0xd)))
)
}
}
}
文件 2 的 5:ERC20Interface.sol
pragma solidity 0.7.5;
abstract contract ERC20Interface {
function transfer(address _to, uint256 _value)
public
virtual
returns (bool success);
function balanceOf(address _owner)
public
virtual
view
returns (uint256 balance);
}
文件 3 的 5:Forwarder.sol
pragma solidity 0.7.5;
import '@uniswap/lib/contracts/libraries/TransferHelper.sol';
import './ERC20Interface.sol';
contract Forwarder {
address public parentAddress;
event ForwarderDeposited(address from, uint256 value, bytes data);
function init(address _parentAddress) external onlyUninitialized {
parentAddress = _parentAddress;
uint256 value = address(this).balance;
if (value == 0) {
return;
}
(bool success, ) = parentAddress.call{ value: value }('');
require(success, 'Flush failed');
emit ForwarderDeposited(address(this), value, msg.data);
}
modifier onlyParent {
require(msg.sender == parentAddress, 'Only Parent');
_;
}
modifier onlyUninitialized {
require(parentAddress == address(0x0), 'Already initialized');
_;
}
fallback() external payable {
flush();
}
receive() external payable {
flush();
}
function flushTokens(address tokenContractAddress) external onlyParent {
ERC20Interface instance = ERC20Interface(tokenContractAddress);
address forwarderAddress = address(this);
uint256 forwarderBalance = instance.balanceOf(forwarderAddress);
if (forwarderBalance == 0) {
return;
}
TransferHelper.safeTransfer(
tokenContractAddress,
parentAddress,
forwarderBalance
);
}
function flush() public {
uint256 value = address(this).balance;
if (value == 0) {
return;
}
(bool success, ) = parentAddress.call{ value: value }('');
require(success, 'Flush failed');
emit ForwarderDeposited(msg.sender, value, msg.data);
}
}
文件 4 的 5:ForwarderFactory.sol
pragma solidity 0.7.5;
import './Forwarder.sol';
import './CloneFactory.sol';
contract ForwarderFactory is CloneFactory {
address public implementationAddress;
event ForwarderCreated(address newForwarderAddress, address parentAddress);
constructor(address _implementationAddress) {
implementationAddress = _implementationAddress;
}
function createForwarder(address parent, bytes32 salt) external {
bytes32 finalSalt = keccak256(abi.encodePacked(parent, salt));
address payable clone = createClone(implementationAddress, finalSalt);
Forwarder(clone).init(parent);
emit ForwarderCreated(clone, parent);
}
}
文件 5 的 5:TransferHelper.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');
}
}
{
"compilationTarget": {
"ForwarderFactory.sol": "ForwarderFactory"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_implementationAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newForwarderAddress","type":"address"},{"indexed":false,"internalType":"address","name":"parentAddress","type":"address"}],"name":"ForwarderCreated","type":"event"},{"inputs":[{"internalType":"address","name":"parent","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"createForwarder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"implementationAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]