github.com/Onther-Tech/plasma-evm@v0.0.0-rc7.7/contracts/stamina/stamina_test.go (about) 1 package stamina 2 3 import ( 4 "context" 5 "crypto/ecdsa" 6 "encoding/hex" 7 "math/big" 8 "testing" 9 10 "github.com/Onther-Tech/plasma-evm/accounts/abi/bind" 11 "github.com/Onther-Tech/plasma-evm/accounts/abi/bind/backends" 12 "github.com/Onther-Tech/plasma-evm/common" 13 "github.com/Onther-Tech/plasma-evm/consensus/ethash" 14 "github.com/Onther-Tech/plasma-evm/core" 15 "github.com/Onther-Tech/plasma-evm/core/rawdb" 16 "github.com/Onther-Tech/plasma-evm/core/types" 17 "github.com/Onther-Tech/plasma-evm/core/vm" 18 "github.com/Onther-Tech/plasma-evm/crypto" 19 "github.com/Onther-Tech/plasma-evm/params" 20 ) 21 22 var ( 23 delegateeKey, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 24 delegateeAddr = crypto.PubkeyToAddress(delegateeKey.PublicKey) 25 delegateeOpt = bind.NewKeyedTransactor(delegateeKey) 26 27 depositorAddr = delegateeAddr 28 29 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 30 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 31 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 32 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 33 opt1 = bind.NewKeyedTransactor(key1) 34 opt2 = bind.NewKeyedTransactor(key2) 35 ) 36 37 var ( 38 stamina = big.NewInt(5000000000) 39 minDeposit = big.NewInt(100) 40 recoveryEpochLength = big.NewInt(10) 41 withdrawalDelay = big.NewInt(50) 42 ) 43 44 func TestStamina(t *testing.T) { 45 staminaBinBytes, err := hex.DecodeString(params.StaminaContractDeployedBin[2:]) 46 if err != nil { 47 panic(err) 48 } 49 50 contractBackend := backends.NewSimulatedBackend(core.GenesisAlloc{ 51 delegateeAddr: {Balance: big.NewInt(10000000000)}, 52 addr1: {Balance: big.NewInt(0)}, 53 addr2: {Balance: big.NewInt(10000000000)}, 54 params.StaminaAddress: { 55 Code: staminaBinBytes, 56 Balance: big.NewInt(0), 57 }, 58 }, 10000000000) 59 60 staminaContract, err := NewStamina(delegateeOpt, params.StaminaAddress, contractBackend) 61 if err != nil { 62 t.Fatalf("expected no error, got %v", err) 63 } 64 65 // init 66 if _, err := staminaContract.Init(minDeposit, recoveryEpochLength, withdrawalDelay); err != nil { 67 t.Fatalf("expected no error, got %v", err) 68 } 69 contractBackend.Commit() 70 71 initialized, err := staminaContract.Initialized() 72 if err != nil { 73 t.Fatalf("expected no error, got %v", err) 74 } 75 if !initialized { 76 t.Errorf("expected: %v, got %v", false, initialized) 77 } 78 79 staminaContract.TransactOpts.Value = stamina 80 // deposit 81 if _, err := staminaContract.Deposit(delegateeAddr); err != nil { 82 t.Fatalf("expected no error, got %v", err) 83 } 84 contractBackend.Commit() 85 86 deposit, err := staminaContract.GetDeposit(depositorAddr, delegateeAddr) 87 if err != nil { 88 t.Fatalf("expected no error, got %v", err) 89 } 90 if deposit.Cmp(stamina) != 0 { 91 t.Errorf("expected: %v, got %v", stamina, deposit) 92 } 93 94 // Eth : short 95 // Stamina: short 96 if err := sendSignedTransferTransaction(contractBackend, addr1, key1); err == nil { 97 t.Fatal("expected insufficient balance to pay for gas") 98 } 99 100 // Eth : short 101 // Stamina: enough 102 staminaContract.TransactOpts = *delegateeOpt 103 if _, err = staminaContract.SetDelegator(addr1); err != nil { 104 t.Fatalf("expected no error, got %v", err) 105 } 106 contractBackend.Commit() 107 108 delegatee, err := staminaContract.GetDelegatee(addr1) 109 if err != nil { 110 t.Fatalf("expected no error, got %v", err) 111 } 112 if delegatee != delegateeAddr { 113 t.Errorf("expected: %v, got %v", delegateeAddr, delegatee) 114 } 115 116 staminaContract.TransactOpts = *opt1 117 beforeStaminaRemaining, _ := staminaContract.GetStamina(delegateeAddr) 118 beforeBalance, _ := contractBackend.BalanceAt(context.Background(), addr1, contractBackend.CurrentBlock()) 119 120 if err := sendSignedTransferTransaction(contractBackend, addr1, key1); err != nil { 121 t.Fatalf("expected no error, got %v", err) 122 } 123 contractBackend.Commit() 124 125 afterStaminaRemaining, _ := staminaContract.GetStamina(delegateeAddr) 126 afterBalance, _ := contractBackend.BalanceAt(context.Background(), addr1, contractBackend.CurrentBlock()) 127 128 if beforeBalance.Cmp(afterBalance) != 0 { 129 t.Errorf("balance before: %v, after %v", beforeBalance, afterBalance) 130 } 131 if beforeStaminaRemaining.Cmp(new(big.Int).Add(afterStaminaRemaining, big.NewInt(21000))) != 0 { 132 t.Error("failed precise stamina subtract") 133 } 134 135 // Eth : enough 136 // Stamina: short 137 staminaContract.TransactOpts = *opt2 138 beforeStaminaRemaining, _ = staminaContract.GetStamina(delegateeAddr) 139 beforeBalance, _ = contractBackend.BalanceAt(context.Background(), addr2, contractBackend.CurrentBlock()) 140 141 if err := sendSignedTransferTransaction(contractBackend, addr2, key2); err != nil { 142 t.Fatalf("expected no error, got %v", err) 143 } 144 contractBackend.Commit() 145 146 afterStaminaRemaining, _ = staminaContract.GetStamina(delegateeAddr) 147 afterBalance, _ = contractBackend.BalanceAt(context.Background(), addr2, contractBackend.CurrentBlock()) 148 149 if beforeBalance.Cmp(new(big.Int).Add(afterBalance, big.NewInt(21000))) != 0 { 150 t.Error("failed precise balance subtract") 151 } 152 if beforeStaminaRemaining.Cmp(afterStaminaRemaining) != 0 { 153 t.Errorf("stamina before: %v, after %v", beforeStaminaRemaining, afterStaminaRemaining) 154 } 155 156 // Eth : enough 157 // Stamina: enough 158 staminaContract.TransactOpts = *delegateeOpt 159 if _, err := staminaContract.SetDelegator(addr2); err != nil { 160 t.Fatalf("expected no error, got %v", err) 161 } 162 contractBackend.Commit() 163 164 delegatee, err = staminaContract.GetDelegatee(addr2) 165 if err != nil { 166 t.Fatalf("expected no error, got %v", err) 167 } 168 if delegatee != delegateeAddr { 169 t.Errorf("expected: %v, got %v", delegateeAddr, delegatee) 170 } 171 172 staminaContract.TransactOpts = *opt2 173 beforeStaminaRemaining, _ = staminaContract.GetStamina(delegateeAddr) 174 beforeBalance, _ = contractBackend.BalanceAt(context.Background(), addr2, contractBackend.CurrentBlock()) 175 176 if err := sendSignedTransferTransaction(contractBackend, addr2, key2); err != nil { 177 t.Fatalf("expected no error, got %v", err) 178 } 179 contractBackend.Commit() 180 181 afterStaminaRemaining, _ = staminaContract.GetStamina(delegateeAddr) 182 afterBalance, _ = contractBackend.BalanceAt(context.Background(), addr2, contractBackend.CurrentBlock()) 183 184 if beforeBalance.Cmp(afterBalance) != 0 { 185 t.Errorf("balance before: %v, after %v", beforeBalance, afterBalance) 186 } 187 if beforeStaminaRemaining.Cmp(new(big.Int).Add(afterStaminaRemaining, big.NewInt(21000))) != 0 { 188 t.Error("failed precise stamina subtract") 189 } 190 } 191 192 func TestGetDefaultStaminaFromStorageKey(t *testing.T) { 193 var ( 194 defaultStaminaConfig = params.DefaultStaminaConfig 195 operator = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7") 196 ) 197 198 gspec := core.DefaultGenesisBlock(common.Address{}, operator, defaultStaminaConfig) 199 db := rawdb.NewMemoryDatabase() 200 gspec.MustCommit(db) 201 blockchain, _ := core.NewBlockChain(db, nil, params.MainnetChainConfig, ethash.NewFaker(), vm.Config{EnablePreimageRecording: true}, nil) 202 203 statedb, _ := blockchain.State() 204 stamina := statedb.GetState(params.StaminaAddress, params.GetStaminaKey(operator)) 205 if common.BytesToHash(params.DefaultOperatorStamina.Bytes()) != common.BytesToHash(stamina.Bytes()) { 206 t.Fatalf("unexpected value: want %x, got %x", params.DefaultOperatorStamina, stamina) 207 } 208 } 209 210 func TestStaminaGenesisConfig(t *testing.T) { 211 defaultStaminaConfig := params.DefaultStaminaConfig 212 g := core.DefaultGenesisBlock(common.Address{}, common.Address{1}, defaultStaminaConfig) 213 gNumber := big.NewInt(0) 214 ctx := context.Background() 215 contractBackend := backends.NewSimulatedBackend(g.Alloc, 10000000000) 216 217 initialized, err := contractBackend.StorageAt(ctx, params.StaminaAddress, params.StaminaInitializedKey, gNumber) 218 if !common.ByteToBool(initialized[31]) { 219 t.Errorf("unexpected value: want %t, got %t", true, common.ByteToBool(initialized[31])) 220 } 221 if err != nil { 222 t.Fatalf("expected no error, got %v", err) 223 } 224 225 minDeposit, err := contractBackend.StorageAt(ctx, params.StaminaAddress, params.StaminaMinDepositKey, gNumber) 226 if common.BytesToHash(minDeposit) != common.BytesToHash(defaultStaminaConfig.MinDeposit.Bytes()) { 227 t.Errorf("unexpected value: want %x, got %x", common.ToHex(defaultStaminaConfig.MinDeposit.Bytes()), common.ToHex(minDeposit)) 228 } 229 if err != nil { 230 t.Fatalf("expected no error, got %v", err) 231 } 232 233 recoverEpochLength, err := contractBackend.StorageAt(ctx, params.StaminaAddress, params.StaminaRecoverEpochLengthKey, gNumber) 234 if common.BytesToHash(recoverEpochLength) != common.BytesToHash(defaultStaminaConfig.RecoverEpochLength.Bytes()) { 235 t.Errorf("unexpected value: want %x, got %x", common.ToHex(defaultStaminaConfig.RecoverEpochLength.Bytes()), common.ToHex(recoverEpochLength)) 236 } 237 if err != nil { 238 t.Fatalf("expected no error, got %v", err) 239 } 240 241 withdrawalDelay, err := contractBackend.StorageAt(ctx, params.StaminaAddress, params.StaminaWithdrawalDelayKey, gNumber) 242 if common.BytesToHash(withdrawalDelay) != common.BytesToHash(defaultStaminaConfig.WithdrawalDelay.Bytes()) { 243 t.Errorf("unexpected value: want %x, got %x", common.ToHex(defaultStaminaConfig.WithdrawalDelay.Bytes()), common.ToHex(withdrawalDelay)) 244 } 245 if err != nil { 246 t.Fatalf("expected no error, got %v", err) 247 } 248 } 249 250 func sendSignedTransferTransaction(contractBackend *backends.SimulatedBackend, addr common.Address, key *ecdsa.PrivateKey) (err error) { 251 defer func() { 252 if r := recover(); r != nil { 253 err = r.(error) 254 } 255 }() 256 257 nonce, err := contractBackend.NonceAt(context.Background(), addr, contractBackend.CurrentBlock()) 258 if err != nil { 259 return err 260 } 261 signedTx, err := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(1), nil), types.HomesteadSigner{}, key) 262 if err != nil { 263 return err 264 } 265 err = contractBackend.SendTransaction(context.Background(), signedTx) 266 if err != nil { 267 return err 268 } 269 270 return nil 271 }