Skip to content

Instantly share code, notes, and snippets.

@JingwenTian
Last active May 9, 2022 17:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JingwenTian/f9ce513157bd540511e2577914092304 to your computer and use it in GitHub Desktop.
Save JingwenTian/f9ce513157bd540511e2577914092304 to your computer and use it in GitHub Desktop.
《加密货币聚合支付技术方案思考》代码示例
pragma solidity >=0.7.0 <0.9.0;
contract Account {
constructor(address payable _reciever) {
// 将1%的收入作为平台佣金转移至平台账户
payable(0x07533963Da0494A48a763C82359DC131a79011f0).transfer(address(this).balance * 1 / 100);
// 合约的用途仅用于一次收款和一次资金转移, 所以用完后可以直接销毁
// 通过自毁函数销毁合约, 强制将剩余的资金转移至商户的账户, 且得到部分Gas返还
selfdestruct(_reciever);
}
}
package main
import (
"fmt"
"strings"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"encoding/hex"
"golang.org/x/crypto/sha3"
)
const ABIDATA = `[
{
"inputs": [
{
"internalType": "address payable",
"name": "_reciever",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
}
]`
func main() {
// ABIDATA 为 Account 合约 ABI json
parsed, err := abi.JSON(strings.NewReader(ABIDATA))
if err != nil {
panic(err)
}
// Account 合约构造函数设置了 reciever 参数
// reciever 是商户的入账钱包地址,这个需要持久化保存
const reciever = "0x90239D619797bbcA069deE9320E79a76951b8ced"
param, err := parsed.Pack("", common.HexToAddress(reciever))
if err != nil {
panic(err)
}
// 计算 Account 合约初始化哈希
const bytecode = "608060405234801561001057600080fd5b50604051610242380380610242833981810160405281019061003291906100d3565b7307533963da0494a48a763c82359dc131a79011f073ffffffffffffffffffffffffffffffffffffffff166108fc606460014761006f9190610131565b6100799190610100565b9081150290604051600060405180830381858888f193505050501580156100a4573d6000803e3d6000fd5b508073ffffffffffffffffffffffffffffffffffffffff16ff5b6000815190506100cd8161022a565b92915050565b6000602082840312156100e9576100e8610225565b5b60006100f7848285016100be565b91505092915050565b600061010b826101bd565b9150610116836101bd565b925082610126576101256101f6565b5b828204905092915050565b600061013c826101bd565b9150610147836101bd565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156101805761017f6101c7565b5b828202905092915050565b60006101968261019d565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600080fd5b6102338161018b565b811461023e57600080fd5b5056fe"
inithash := Keccak256(MustHexDecode(bytecode), param)
// Wallet 合约地址
address := MustHexDecode("0x4d3e2C755aCCeDb752878b2E025Bdfa2cFE7116C")
// 自定义一个 32 字节的 salt 值,这个需要持久化保存到数据库内(可以通过交易单ID计算获得)
salt := MustHexDecode("0x844e2b5a3210a359906614364618e2991ecd95223bdaf2733ade658613540a9d")
// CREATE2 定义了新的账户生成方式:keccak256( 0xff ++ address ++ salt ++ keccak256(init_code))[12:]
// ↑ 这里的 address 还是指发送者账户,可以是合约账户,也可以是外部账户;salt 是额外的数据,固定为 32 字节,开发者可以随意控制;init_code 是合约初始化代码及其参数。
// 预先计算出用于收款的合约地址 0xdebedc5e19376c4c2c8b365d47cf7dc031cd7a7a
addr := "0x" + hex.EncodeToString(Keccak256([]byte{0xff}, address, salt, inithash)[12:])
fmt.Println(addr)
}
// 上面的示例代码使用了下面辅助函数
func MustHexDecode(raw string) []byte {
if raw == "0x" {
return []byte{}
}
if len(raw) > 2 && raw[:2] == "0x" {
raw = raw[2:]
}
data, err := hex.DecodeString(raw)
if err != nil {
panic(err)
}
return data
}
func Keccak256(data ...[]byte) []byte {
d := sha3.NewLegacyKeccak256()
for _, b := range data {
_, _ = d.Write(b)
}
return d.Sum(nil)
}
pragma solidity >=0.7.0 <0.9.0;
import "./Account.sol";
contract Wallet {
address public admin;
event Create(address);
constructor() {
admin = msg.sender;
}
modifier OnlyAdmin {
require(msg.sender == admin, "403");
_;
}
function create(address payable _to, bytes32 _salt) public OnlyAdmin {
Account a = new Account{salt: _salt}(_to);
emit Create(address(a));
}
}
@JingwenTian
Copy link
Author

JingwenTian commented May 6, 2022

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment