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  }