Skip to content

Instantly share code, notes, and snippets.

@k06a
Created February 16, 2022 11:28
Show Gist options
  • Save k06a/0ea02ecd824bd3d44c760825b62bc264 to your computer and use it in GitHub Desktop.
Save k06a/0ea02ecd824bd3d44c760825b62bc264 to your computer and use it in GitHub Desktop.
ERC20 extension with create2-based factory for arbitrary calls
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/Create2.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "github.com/1inch/solidity-utils/contracts/libraries/AddressArray.sol";
contract Caller {
address public immutable immutableOwner = msg.sender;
function makeCall(address to, bytes memory data) public {
require(msg.sender == immutableOwner, "Caller: access denied");
(bool success,) = to.call(data);
require(success);
}
}
abstract contract ERC20WithFactory is ERC20 {
using AddressArray for AddressArray.Data;
AddressArray.Data private _callers;
bytes32 public immutable callerHash;
constructor() {
callerHash = keccak256(type(Caller).creationCode);
}
function approveAndCall(address to, uint256 amount, bytes memory data) public returns(bool) {
approve(to, amount);
_callers.push(msg.sender);
bytes32 salt = bytes32(bytes20(msg.sender));
address caller = Create2.computeAddress(salt, callerHash);
if (caller.code.length == 0) {
Create2.deploy(0, salt, type(Caller).creationCode);
}
Caller(caller).makeCall(to, data);
_callers.pop();
return true;
}
function transferFrom(address from, address to, uint256 amount) public virtual override returns(bool) {
address[] memory callers = _callers.get();
for (uint256 i = 0; i < callers.length; i++) {
bytes32 salt = bytes32(bytes20(callers[i]));
address caller = Create2.computeAddress(salt, callerHash);
if (msg.sender == caller) {
return super.transferFrom(callers[i], to, amount);
}
}
return super.transferFrom(from, to, amount);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment