Web Developer DeFi
Web Developer DeFi
Share Dialog
Share Dialog

Subscribe to Smithereens

Subscribe to Smithereens
应用场景:
类似 uniswap 去中心化交易所池子合约计算。Uniswap v2 工厂合约计算 pair 合约地址的利用了该特性。但其中需要注意的点是:当我们使用 type(constract).creationCode 时需要注意合约元数据的变化,编译器版本的不同也有可能影响到字节码的变化,具体文档如下。(自行部署 Uniswap 代码时可能遇到该问题)
https://learnblockchain.cn/docs/solidity/metadata.html#encoding-of-the-metadata-hash-in-the-bytecode
https://github.com/Uniswap/v2-periphery/blob/master/contracts/libraries/UniswapV2Library.sol
https://github.com/Uniswap/v2-core/blob/master/contracts/UniswapV2Factory.sol
解决交易所充值账号问题
如果为每个用户创建一个地址,则私钥的维护是个问题,如果单独的一个合约地址那必须要先先部署(浪费gas)才能看到地址,所以利用地址预测的方式,需要的时候再创建。
示例代码如下:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
contract Factory {
// Returns the address of the newly deployed contract
function deploy(
address _owner,
uint _foo,
bytes32 _salt
) public payable returns (address) {
// This syntax is a newer way to invoke create2 without assembly, you just need to pass salt
// https://docs.soliditylang.org/en/latest/control-structures.html#salted-contract-creations-create2
return address(new TestContract{salt: _salt}(_owner, _foo));
}
}
// This is the older way of doing it using assembly
contract FactoryAssembly {
event Deployed(address addr, uint salt);
// 1. Get bytecode of contract to be deployed
// NOTE: _owner and _foo are arguments of the TestContract's constructor
function getBytecode(address _owner, uint _foo) public pure returns (bytes memory) {
bytes memory bytecode = type(TestContract).creationCode;
return abi.encodePacked(bytecode, abi.encode(_owner, _foo));
}
// 2. Compute the address of the contract to be deployed
// NOTE: _salt is a random number used to create an address
function getAddress(bytes memory bytecode, uint _salt)
public
view
returns (address)
{
bytes32 hash = keccak256(
abi.encodePacked(bytes1(0xff), address(this), _salt, keccak256(bytecode))
);
// NOTE: cast last 20 bytes of hash to address
return address(uint160(uint(hash)));
}
// 3. Deploy the contract
// NOTE:
// Check the event log Deployed which contains the address of the deployed TestContract.
// The address in the log should equal the address computed from above.
function deploy(bytes memory bytecode, uint _salt) public payable {
address addr;
/*
NOTE: How to call create2
create2(v, p, n, s)
create new contract with code at memory p to p + n
and send v wei
and return the new address
where new address = first 20 bytes of keccak256(0xff + address(this) + s + keccak256(mem[p…(p+n)))
s = big-endian 256-bit value
*/
assembly {
addr := create2(
callvalue(), // wei sent with current call
// Actual code starts after skipping the first 32 bytes
add(bytecode, 0x20),
mload(bytecode), // Load the size of code contained in the first 32 bytes
_salt // Salt from function arguments
)
if iszero(extcodesize(addr)) {
revert(0, 0)
}
}
emit Deployed(addr, _salt);
}
}
contract TestContract {
address public owner;
uint public foo;
constructor(address _owner, uint _foo) payable {
owner = _owner;
foo = _foo;
}
function getBalance() public view returns (uint) {
return address(this).balance;
}
}
应用场景:
类似 uniswap 去中心化交易所池子合约计算。Uniswap v2 工厂合约计算 pair 合约地址的利用了该特性。但其中需要注意的点是:当我们使用 type(constract).creationCode 时需要注意合约元数据的变化,编译器版本的不同也有可能影响到字节码的变化,具体文档如下。(自行部署 Uniswap 代码时可能遇到该问题)
https://learnblockchain.cn/docs/solidity/metadata.html#encoding-of-the-metadata-hash-in-the-bytecode
https://github.com/Uniswap/v2-periphery/blob/master/contracts/libraries/UniswapV2Library.sol
https://github.com/Uniswap/v2-core/blob/master/contracts/UniswapV2Factory.sol
解决交易所充值账号问题
如果为每个用户创建一个地址,则私钥的维护是个问题,如果单独的一个合约地址那必须要先先部署(浪费gas)才能看到地址,所以利用地址预测的方式,需要的时候再创建。
示例代码如下:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
contract Factory {
// Returns the address of the newly deployed contract
function deploy(
address _owner,
uint _foo,
bytes32 _salt
) public payable returns (address) {
// This syntax is a newer way to invoke create2 without assembly, you just need to pass salt
// https://docs.soliditylang.org/en/latest/control-structures.html#salted-contract-creations-create2
return address(new TestContract{salt: _salt}(_owner, _foo));
}
}
// This is the older way of doing it using assembly
contract FactoryAssembly {
event Deployed(address addr, uint salt);
// 1. Get bytecode of contract to be deployed
// NOTE: _owner and _foo are arguments of the TestContract's constructor
function getBytecode(address _owner, uint _foo) public pure returns (bytes memory) {
bytes memory bytecode = type(TestContract).creationCode;
return abi.encodePacked(bytecode, abi.encode(_owner, _foo));
}
// 2. Compute the address of the contract to be deployed
// NOTE: _salt is a random number used to create an address
function getAddress(bytes memory bytecode, uint _salt)
public
view
returns (address)
{
bytes32 hash = keccak256(
abi.encodePacked(bytes1(0xff), address(this), _salt, keccak256(bytecode))
);
// NOTE: cast last 20 bytes of hash to address
return address(uint160(uint(hash)));
}
// 3. Deploy the contract
// NOTE:
// Check the event log Deployed which contains the address of the deployed TestContract.
// The address in the log should equal the address computed from above.
function deploy(bytes memory bytecode, uint _salt) public payable {
address addr;
/*
NOTE: How to call create2
create2(v, p, n, s)
create new contract with code at memory p to p + n
and send v wei
and return the new address
where new address = first 20 bytes of keccak256(0xff + address(this) + s + keccak256(mem[p…(p+n)))
s = big-endian 256-bit value
*/
assembly {
addr := create2(
callvalue(), // wei sent with current call
// Actual code starts after skipping the first 32 bytes
add(bytecode, 0x20),
mload(bytecode), // Load the size of code contained in the first 32 bytes
_salt // Salt from function arguments
)
if iszero(extcodesize(addr)) {
revert(0, 0)
}
}
emit Deployed(addr, _salt);
}
}
contract TestContract {
address public owner;
uint public foo;
constructor(address _owner, uint _foo) payable {
owner = _owner;
foo = _foo;
}
function getBalance() public view returns (uint) {
return address(this).balance;
}
}
<100 subscribers
<100 subscribers
No activity yet