github.com/klaytn/klaytn@v1.10.2/tests/kip103_test.go (about) 1 package tests 2 3 import ( 4 "context" 5 "math/big" 6 "os" 7 "testing" 8 "time" 9 10 "github.com/klaytn/klaytn" 11 "github.com/klaytn/klaytn/accounts/abi/bind" 12 "github.com/klaytn/klaytn/api" 13 "github.com/klaytn/klaytn/blockchain/types" 14 "github.com/klaytn/klaytn/common" 15 "github.com/klaytn/klaytn/common/hexutil" 16 "github.com/klaytn/klaytn/consensus/istanbul" 17 "github.com/klaytn/klaytn/contracts/kip103" 18 "github.com/klaytn/klaytn/log" 19 "github.com/klaytn/klaytn/networks/rpc" 20 "github.com/klaytn/klaytn/node/cn" 21 "github.com/klaytn/klaytn/params" 22 "github.com/stretchr/testify/assert" 23 ) 24 25 type testKip103TxTransactor struct { 26 node *cn.CN 27 } 28 29 func (t *testKip103TxTransactor) FilterLogs(ctx context.Context, query klaytn.FilterQuery) ([]types.Log, error) { 30 return nil, nil 31 } 32 33 func (t *testKip103TxTransactor) SubscribeFilterLogs(ctx context.Context, query klaytn.FilterQuery, ch chan<- types.Log) (klaytn.Subscription, error) { 34 return nil, nil 35 } 36 37 func (t *testKip103TxTransactor) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { 38 return t.CodeAt(ctx, account, nil) 39 } 40 41 func (t *testKip103TxTransactor) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { 42 return t.node.TxPool().GetPendingNonce(account), nil 43 } 44 45 func (t *testKip103TxTransactor) SuggestGasPrice(ctx context.Context) (*big.Int, error) { 46 return big.NewInt(int64(t.node.BlockChain().Config().UnitPrice)), nil 47 } 48 49 func (t *testKip103TxTransactor) EstimateGas(ctx context.Context, call klaytn.CallMsg) (gas uint64, err error) { 50 return uint64(1e8), nil 51 } 52 53 func (t *testKip103TxTransactor) SendTransaction(ctx context.Context, tx *types.Transaction) error { 54 return t.node.TxPool().AddLocal(tx) 55 } 56 57 func (t *testKip103TxTransactor) ChainID(ctx context.Context) (*big.Int, error) { 58 return t.node.BlockChain().Config().ChainID, nil 59 } 60 61 func (t *testKip103TxTransactor) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) { 62 if blockNumber == nil { 63 blockNumber = t.node.BlockChain().CurrentBlock().Number() 64 } 65 root := t.node.BlockChain().GetHeaderByNumber(blockNumber.Uint64()).Root 66 state, err := t.node.BlockChain().StateAt(root) 67 if err != nil { 68 return nil, err 69 } 70 return state.GetCode(contract), nil 71 } 72 73 func (t *testKip103TxTransactor) CallContract(ctx context.Context, call klaytn.CallMsg, blockNumber *big.Int) ([]byte, error) { 74 if blockNumber == nil { 75 blockNumber = t.node.BlockChain().CurrentBlock().Number() 76 } 77 78 price := hexutil.Big(*t.node.TxPool().GasPrice()) 79 if call.GasPrice != nil { 80 price = hexutil.Big(*call.GasPrice) 81 } 82 83 value := hexutil.Big(*big.NewInt(0)) 84 if call.Value != nil { 85 value = hexutil.Big(*call.Value) 86 } 87 88 arg := api.CallArgs{From: call.From, To: call.To, Gas: hexutil.Uint64(1e8), GasPrice: &price, Value: value, Data: call.Data} 89 bn := rpc.BlockNumber(blockNumber.Int64()) 90 91 apiBackend := api.NewPublicBlockChainAPI(t.node.APIBackend) 92 return apiBackend.Call(ctx, arg, rpc.NewBlockNumberOrHashWithNumber(bn)) 93 } 94 95 func TestRebalanceTreasury_EOA(t *testing.T) { 96 log.EnableLogForTest(log.LvlError, log.LvlInfo) 97 98 // prepare chain configuration 99 config := params.CypressChainConfig.Copy() 100 config.LondonCompatibleBlock = big.NewInt(0) 101 config.IstanbulCompatibleBlock = big.NewInt(0) 102 config.EthTxTypeCompatibleBlock = big.NewInt(0) 103 config.MagmaCompatibleBlock = big.NewInt(0) 104 config.KoreCompatibleBlock = big.NewInt(0) 105 config.Istanbul.SubGroupSize = 1 106 config.Istanbul.ProposerPolicy = uint64(istanbul.RoundRobin) 107 config.Governance.Reward.MintingAmount = new(big.Int).Mul(big.NewInt(9000000000000000000), big.NewInt(params.KLAY)) 108 109 // make a blockchain node 110 fullNode, node, validator, _, workspace := newBlockchain(t, config) 111 defer func() { 112 fullNode.Stop() 113 os.RemoveAll(workspace) 114 }() 115 116 optsOwner := bind.NewKeyedTransactor(validator.Keys[0]) 117 transactor := &testKip103TxTransactor{node: node} 118 targetBlockNum := new(big.Int).Add(node.BlockChain().CurrentBlock().Number(), big.NewInt(5)) 119 120 contractAddr, _, contract, err := kip103.DeployTreasuryRebalance(optsOwner, transactor, targetBlockNum) 121 if err != nil { 122 t.Fatal(err) 123 } 124 125 // set kip103 hardfork config 126 node.BlockChain().Config().Kip103CompatibleBlock = targetBlockNum 127 node.BlockChain().Config().Kip103ContractAddress = contractAddr 128 129 t.Log("ContractOwner Addr:", validator.GetAddr().String()) 130 t.Log("Contract Addr:", contractAddr.String()) 131 t.Log("Target Block:", targetBlockNum.Int64()) 132 133 // naive waiting for tx processing 134 time.Sleep(2 * time.Second) 135 136 // prepare newbie accounts 137 numNewbie := 3 138 newbieAccs := make([]TestAccount, numNewbie) 139 newbieAllocs := make([]*big.Int, numNewbie) 140 141 state, err := node.BlockChain().State() 142 if err != nil { 143 t.Fatal(err) 144 } 145 totalNewbieAlloc := state.GetBalance(validator.Addr) 146 t.Log("Total Newbie amount: ", totalNewbieAlloc) 147 148 for i := 0; i < numNewbie; i++ { 149 newbieAccs[i] = genKlaytnLegacyAccount(t) 150 newbieAllocs[i] = new(big.Int).Div(totalNewbieAlloc, big.NewInt(2)) 151 totalNewbieAlloc.Sub(totalNewbieAlloc, newbieAllocs[i]) 152 153 t.Log("Newbie", i, "Addr:", newbieAccs[i].GetAddr().String()) 154 t.Log("Newbie", i, "Amount:", newbieAllocs[i]) 155 } 156 157 // register RegisterRetired 158 if _, err := contract.RegisterRetired(optsOwner, validator.Addr); err != nil { 159 t.Fatal(err) 160 } 161 162 // register newbies 163 for i, newbie := range newbieAccs { 164 if _, err := contract.RegisterNewbie(optsOwner, newbie.GetAddr(), newbieAllocs[i]); err != nil { 165 t.Fatal(err) 166 } 167 } 168 169 // initialized -> registered 170 if _, err := contract.FinalizeRegistration(optsOwner); err != nil { 171 t.Fatal(err) 172 } 173 174 // approve 175 if _, err := contract.Approve(optsOwner, validator.GetAddr()); err != nil { 176 t.Fatal(err) 177 } 178 179 // registered -> approved 180 if _, err := contract.FinalizeApproval(optsOwner); err != nil { 181 t.Fatal(err) 182 } 183 184 header := waitBlock(node.BlockChain(), targetBlockNum.Uint64()) 185 if header == nil { 186 t.Fatal("timeout") 187 } 188 189 curState, err := node.BlockChain().StateAt(header.Root) 190 if err != nil { 191 t.Fatal(err) 192 } 193 194 balRetired := curState.GetBalance(validator.GetAddr()) 195 assert.Equal(t, balRetired, big.NewInt(0)) 196 197 for j, newbie := range newbieAccs { 198 balNewbie := curState.GetBalance(newbie.GetAddr()) 199 assert.Equal(t, newbieAllocs[j], balNewbie) 200 } 201 }