Forwarder
Forwarder
Forwarder
contract CloneFactory {
function createClone(address target, bytes32 salt)
internal
returns (address payable result)
{
bytes20 targetBytes = bytes20(target);
assembly {
// load the next free memory slot as a place to store the clone contract data
let clone := mload(0x40)
// The bytecode block is the actual code that is deployed for each clone
created.
// It forwards all calls to the already deployed implementation via a
delegatecall
mstore(
add(clone, 0x28),
0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
)
// The next three lines store the expected bytecode for a miniml proxy
// that targets `target` as its implementation contract
mstore(
clone,
0x363d3d373d3d3d363d7300000000000000000000000000000000000000000000
)
mstore(add(clone, 0xa), targetBytes)
mstore(
add(clone, 0x1e),
0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
)
// the next two lines store the bytecode of the contract that we are checking
in memory
let other := add(clone, 0x40)
extcodecopy(query, other, 0, 0x2d)
// Check if the expected bytecode equals the actual bytecode and return the
result
result := and(
eq(mload(clone), mload(other)),
eq(mload(add(clone, 0xd)), mload(add(other, 0xd)))
)
}
}
}
/**
* Contract that exposes the needed erc20 token functions
*/
// helper methods for interacting with ERC20 tokens and sending ETH that do not
consistently return true/false
library TransferHelper {
function safeApprove(
address token,
address to,
uint256 value
) internal {
// bytes4(keccak256(bytes('approve(address,uint256)')));
(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 {
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(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 {
// bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
(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'
);
}
/**
* Contract that will forward any incoming Ether to the creator of the contract
*
*/
contract Forwarder {
// Address to which any funds sent to this contract will be forwarded
address public parentAddress;
event ForwarderDeposited(address from, uint256 value, bytes data);
/**
* Initialize the contract, and sets the destination address to that of the
creator
*/
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');
// NOTE: since we are forwarding on initialization,
// we don't have the context of the original sender.
// We still emit an event about the forwarding but set
// the sender to the forwarder itself
emit ForwarderDeposited(address(this), value, msg.data);
}
/**
* Modifier that will execute internal code block only if the sender is the
parent address
*/
modifier onlyParent {
require(msg.sender == parentAddress, 'Only Parent');
_;
}
/**
* Modifier that will execute internal code block only if the contract has not
been initialized yet
*/
modifier onlyUninitialized {
require(parentAddress == address(0x0), 'Already initialized');
_;
}
/**
* Default function; Gets called when data is sent but does not match any other
function
*/
fallback() external payable {
flush();
}
/**
* Default function; Gets called when Ether is deposited with no data, and
forwards it to the parent address
*/
receive() external payable {
flush();
}
/**
* Execute a token transfer of the full balance from the forwarder token to the
parent address
* @param tokenContractAddress the address of the erc20 token contract
*/
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
);
}
/**
* Flush the entire balance of the contract to the parent address.
*/
function flush() public {
uint256 value = address(this).balance;
if (value == 0) {
return;
}
constructor(address _implementationAddress) {
implementationAddress = _implementationAddress;
}