Skip to content

Instantly share code, notes, and snippets.

@kennethhutw
Created April 26, 2023 07:41
Show Gist options
  • Save kennethhutw/2b99c6830d2cfe2d1f62f623ff6fa771 to your computer and use it in GitHub Desktop.
Save kennethhutw/2b99c6830d2cfe2d1f62f623ff6fa771 to your computer and use it in GitHub Desktop.
pragma solidity ^0.5.0;
contract MetaCoinClonable {
mapping (address => uint) balances;
function initialize(address metaCoinOwner, uint256 initialBalance) public {
balances[metaCoinOwner] = initialBalance;
}
function sendCoin(address receiver, uint amount) public returns(bool sufficient) {
if (balances[msg.sender] < amount) return false;
balances[msg.sender] -= amount;
balances[receiver] += amount;
return true;
}
function getBalance(address addr) view public returns(uint) {
return balances[addr];
}
}
contract Ownable {
/**
* @dev Event to show ownership has been transferred
* @param previousOwner representing the address of the previous owner
* @param newOwner representing the address of the new owner
*/
event OwnershipTransferred(address previousOwner, address newOwner);
// Owner of the contract
address private _owner;
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner());
_;
}
/**
* @dev The constructor sets the original owner of the contract to the sender account.
*/
constructor() public {
setOwner(msg.sender);
}
/**
* @dev Tells the address of the owner
* @return the address of the owner
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Sets a new owner address
*/
function setOwner(address newOwner) internal {
_owner = newOwner;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0));
emit OwnershipTransferred(owner(), newOwner);
setOwner(newOwner);
}
}
// https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol
contract CloneFactory {
function createClone(address target) internal returns (address result) {
bytes20 targetBytes = bytes20(target);
assembly {
let clone := mload(0x40)
mstore(clone, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(clone, 0x14), targetBytes)
mstore(add(clone, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
result := create(0, clone, 0x37)
}
}
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)))
)
}
}
}
contract MetaCoinCloneFactory is CloneFactory, Ownable {
MetaCoinClonable[] public metaCoinAddresses;
event MetaCoinCreated(MetaCoinClonable metaCoin);
address public libraryAddress;
address public metaCoinOwner;
function setLibraryAddress(address _libraryAddress) external onlyOwner {
libraryAddress = _libraryAddress;
}
function createMetaCoin(address _metaCoinOwner, uint256 initialBalance) external {
MetaCoinClonable metaCoin = MetaCoinClonable(
createClone(libraryAddress)
);
metaCoin.initialize(_metaCoinOwner, initialBalance);
metaCoinAddresses.push(metaCoin);
emit MetaCoinCreated(metaCoin);
}
function getMetaCoins() external view returns (MetaCoinClonable[] memory) {
return metaCoinAddresses;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment