83 lines
3.1 KiB
Solidity
83 lines
3.1 KiB
Solidity
library CloneFactory {
|
|
function _createClone(address target) internal returns (address result) {
|
|
// convert address to 20 bytes
|
|
bytes20 targetBytes = bytes20(target);
|
|
|
|
// actual code //
|
|
// 3d602d80600a3d3981f3363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe5af43d82803e903d91602b57fd5bf3
|
|
|
|
// creation code //
|
|
// copy runtime code into memory and return it
|
|
// 3d602d80600a3d3981f3
|
|
|
|
// runtime code //
|
|
// code to delegatecall to address
|
|
// 363d3d373d3d3d363d73 address 5af43d82803e903d91602b57fd5bf3
|
|
|
|
assembly {
|
|
/*
|
|
reads the 32 bytes of memory starting at pointer stored in 0x40
|
|
|
|
In solidity, the 0x40 slot in memory is special: it contains the "free memory pointer"
|
|
which points to the end of the currently allocated memory.
|
|
*/
|
|
let clone := mload(0x40)
|
|
// store 32 bytes to memory starting at "clone"
|
|
mstore(
|
|
clone,
|
|
0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000
|
|
)
|
|
|
|
/*
|
|
| 20 bytes |
|
|
0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000
|
|
^
|
|
pointer
|
|
*/
|
|
// store 32 bytes to memory starting at "clone" + 20 bytes
|
|
// 0x14 = 20
|
|
mstore(add(clone, 0x14), targetBytes)
|
|
|
|
/*
|
|
| 20 bytes | 20 bytes |
|
|
0x3d602d80600a3d3981f3363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe
|
|
^
|
|
pointer
|
|
*/
|
|
// store 32 bytes to memory starting at "clone" + 40 bytes
|
|
// 0x28 = 40
|
|
mstore(
|
|
add(clone, 0x28),
|
|
0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
|
|
)
|
|
|
|
/*
|
|
| 20 bytes | 20 bytes | 15 bytes |
|
|
0x3d602d80600a3d3981f3363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe5af43d82803e903d91602b57fd5bf3
|
|
*/
|
|
// create new contract
|
|
// send 0 Ether
|
|
// code starts at pointer stored in "clone"
|
|
// code size 0x37 (55 bytes)
|
|
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)))
|
|
)
|
|
}
|
|
}
|
|
}
|