Skip to content

Instantly share code, notes, and snippets.

@hihiben
Created August 19, 2022 10:04
Show Gist options
  • Save hihiben/d803ab39e922e96c22ed3a36725a40cb to your computer and use it in GitHub Desktop.
Save hihiben/d803ab39e922e96c22ed3a36725a40cb to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.8.16+commit.07a7930e.js&optimize=false&runs=200&gist=
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
contract ContractFactory {
function deploy(uint256 n_, bytes calldata code_) external payable returns (address) {
Proxy p;
try new Proxy{salt: bytes32(n_)}() returns (Proxy _p) {
p = _p;
} catch {
revert("Deploy proxy failed");
}
(bool ok, bytes memory ret) = address(p).call{value: msg.value}(code_);
require(ok, "Deploy failed");
(address target) = abi.decode(ret, (address));
return target;
}
function kill(uint256 n_) external payable {
Proxy p = getProxy(n_);
p.kill();
}
function getProxy(uint256 n_) public view returns (Proxy) {
address predictedAddress = address(uint160(uint(keccak256(abi.encodePacked(
bytes1(0xff),
address(this),
bytes32(n_),
keccak256(abi.encodePacked(
type(Proxy).creationCode
))
)))));
return Proxy(payable(predictedAddress));
}
}
abstract contract Replaceable {
function kill() external {
selfdestruct(payable(msg.sender));
}
}
contract Proxy {
Replaceable public target;
fallback(bytes calldata code_) external payable returns (bytes memory) {
require(address(target) == address(0), "Dirty");
bytes memory code = code_;
address deployedAddress;
assembly {
deployedAddress := create(callvalue(), add(code, 0x20), mload(code))
if iszero(extcodesize(deployedAddress)) {revert(0, 0)}
}
target = Replaceable(deployedAddress);
return abi.encode(deployedAddress);
}
function kill() external {
target.kill();
selfdestruct(payable(msg.sender));
}
}
contract Foo1 is Replaceable {
uint256 public n;
constructor(uint256 n_) {
n = n_;
}
function bar() external pure returns (uint256) {
return 100;
}
function set(uint256 n_) external returns (uint256) {
n = n_;
return n;
}
}
contract Foo2 is Replaceable {
uint256 public n;
string public s;
function bar() external pure returns (string memory) {
return "here";
}
function set(string calldata s_) external returns (string memory) {
s = s_;
return s;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment