Skip to content

Instantly share code, notes, and snippets.

@ajsantander

ajsantander/Changeling.sol

Last active Apr 10, 2019
Embed
What would you like to do?
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.5.1+commit.c8a2cb62.js&optimize=false&gist=
pragma solidity ^0.5.7;
import "./ImplementationProvider.sol";
contract Changeling {
constructor(address implementationProvider) public {
// Request the current implementation address from the provider.
address implementation = ImplementationProvider(implementationProvider).implementation();
// Retrieve the runtime code at the target address.
bytes memory targetCode = getCodeAt(implementation);
// Override Solidity's constructor logic and return the
// retrieved runtime code instead.
assembly {
let size := extcodesize(implementation)
return(0xc0, size)
}
}
function getCodeAt(address _addr) private view returns (bytes memory o_code) {
assembly {
// retrieve the size of the code, this needs assembly
let size := extcodesize(_addr)
// allocate output byte array - this could also be done without assembly
// by using o_code = new bytes(size)
o_code := mload(0x40)
// new "memory end" including padding
mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
// store length in memory
mstore(o_code, size)
// actually retrieve the code, this needs assembly
extcodecopy(_addr, add(o_code, 0x20), 0, size)
}
}
}
function computeAddress(creatorAddress, byteCode, saltNum) {
const saltHex = numberToUint256(saltNum);
return `0x${web3.utils.sha3(`0x${[
'ff',
creatorAddress,
saltHex,
web3.utils.sha3(byteCode)
].map(x => x.replace(/0x/, ''))
.join('')}`).slice(-40)}`.toLowerCase();
}
function numberToUint256(value) {
const hex = value.toString(16)
return `0x${'0'.repeat(64-hex.length)}${hex}`
}
/*
Resulting address:
address = keccak256(
0xff, // 8 byte value
factoryAddress, // current contract's address
salt, // big-endian 256-bit value
keccak256(code) // hash of the code
)
*/
/*
0000000000000000000000000000000000000000000000000000000000000000
*/
computeAddress(
"0x038f160ad632409bfb18582241d9fd88c1a072ba",
"0x608060405234801561001057600080fd5b506102e2806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806335f46994146100465780633fa4f2451461005057806393a09352146100cd575b600080fd5b61004e610173565b005b610058610176565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561009257818101518382015260200161007a565b50505050905090810190601f1680156100bf5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61004e600480360360208110156100e357600080fd5b8101906020810181356401000000008111156100fe57600080fd5b82018360208201111561011057600080fd5b8035906020019184600183028401116401000000008311171561013257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610204945050505050565b33ff5b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156101fc5780601f106101d1576101008083540402835291602001916101fc565b820191906000526020600020905b8154815290600101906020018083116101df57829003601f168201915b505050505081565b805161021790600090602084019061021b565b5050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061025c57805160ff1916838001178555610289565b82800160010185558215610289579182015b8281111561028957825182559160200191906001019061026e565b50610295929150610299565b5090565b6102b391905b80821115610295576000815560010161029f565b9056fea165627a7a723058204f8f8e4f974761044137558685882e74f435626b7940bc4b54c47bedfac4d0cb0029",
42
);
pragma solidity ^0.5.7;
contract CreateFactory {
address public lastCreated;
function create_1(bytes memory code) public {
address addr;
assembly {
addr := create(
0, // value (wei)
add(code, 0x20), // code start position
mload(code) // code length
)
if iszero(extcodesize(addr)) {revert(0, 0)}
}
lastCreated = addr;
}
function create_2(bytes memory code, uint256 salt) public {
address addr;
assembly {
addr := create2(
0, // value (wei)
add(code, 0x20), // code start position
mload(code), // code length
salt // salt
)
if iszero(extcodesize(addr)) {revert(0, 0)}
}
lastCreated = addr;
}
}
pragma solidity ^0.5.7;
contract ImplementationProvider {
address public implementation;
function setImplementation(address _implementation) public {
implementation = _implementation;
}
}
pragma solidity ^0.5.7;
contract Sample {
string public value;
function setValue(string memory _value) public {
value = _value;
}
function die() public {
selfdestruct(msg.sender);
}
}
pragma solidity ^0.5.7;
contract SampleUpgraded {
string public value;
uint256 public anotherValue;
function setValue(string memory _value) public {
value = _value;
}
function setAnotherValue(uint256 _anotherValue) public {
anotherValue = _anotherValue;
}
function die() public {
selfdestruct(msg.sender);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment