From f991479af0585c0ce5c6c7dcd3bb9fffadd7b706 Mon Sep 17 00:00:00 2001 From: skosito Date: Mon, 2 Sep 2024 15:46:27 +0200 Subject: [PATCH] PR comments --- cmd/zetae2e/local/local.go | 4 +- e2e/e2etests/e2etests.go | 8 +- e2e/e2etests/test_precompiles_staking.go | 23 +-- precompiles/staking/IStaking.abi | 30 ++-- precompiles/staking/IStaking.go | 44 ++--- precompiles/staking/IStaking.json | 30 ++-- precompiles/staking/IStaking.sol | 6 +- precompiles/staking/staking.go | 16 +- precompiles/staking/staking_test.go | 195 +++++++++++++++++++---- 9 files changed, 247 insertions(+), 109 deletions(-) diff --git a/cmd/zetae2e/local/local.go b/cmd/zetae2e/local/local.go index b67be69f25..fdde8e5840 100644 --- a/cmd/zetae2e/local/local.go +++ b/cmd/zetae2e/local/local.go @@ -309,8 +309,8 @@ func localE2ETest(cmd *cobra.Command, _ []string) { if !skipPrecompiles { precompiledContractTests = []string{ - e2etests.TestZetaPrecompilesPrototypeName, - e2etests.TestZetaPrecompilesStakingName, + e2etests.TestPrecompilesPrototypeName, + e2etests.TestPrecompilesStakingName, } } diff --git a/e2e/e2etests/e2etests.go b/e2e/e2etests/e2etests.go index ee39269371..7d09bd966c 100644 --- a/e2e/e2etests/e2etests.go +++ b/e2e/e2etests/e2etests.go @@ -147,8 +147,8 @@ const ( /* Stateful precompiled contracts tests */ - TestZetaPrecompilesPrototypeName = "precompile_contracts_prototype" - TestZetaPrecompilesStakingName = "precompile_contracts_staking" + TestPrecompilesPrototypeName = "precompile_contracts_prototype" + TestPrecompilesStakingName = "precompile_contracts_staking" ) // AllE2ETests is an ordered list of all e2e tests @@ -815,13 +815,13 @@ var AllE2ETests = []runner.E2ETest{ Stateful precompiled contracts tests */ runner.NewE2ETest( - TestZetaPrecompilesPrototypeName, + TestPrecompilesPrototypeName, "test stateful precompiled contracts prototype", []runner.ArgDefinition{}, TestPrecompilesPrototype, ), runner.NewE2ETest( - TestZetaPrecompilesStakingName, + TestPrecompilesStakingName, "test stateful precompiled contracts staking", []runner.ArgDefinition{}, TestPrecompilesStaking, diff --git a/e2e/e2etests/test_precompiles_staking.go b/e2e/e2etests/test_precompiles_staking.go index d230706c25..429c63932a 100644 --- a/e2e/e2etests/test_precompiles_staking.go +++ b/e2e/e2etests/test_precompiles_staking.go @@ -3,6 +3,7 @@ package e2etests import ( "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/stretchr/testify/require" "github.com/zeta-chain/node/e2e/runner" @@ -16,18 +17,22 @@ func TestPrecompilesStaking(r *runner.E2ERunner, args []string) { stakingContract, err := staking.NewIStaking(staking.ContractAddress, r.ZEVMClient) require.NoError(r, err, "Failed to create staking contract caller") + previousGasLimit := r.ZEVMAuth.GasLimit r.ZEVMAuth.GasLimit = 10000000 + defer func() { + r.ZEVMAuth.GasLimit = previousGasLimit + }() - validators, err := stakingContract.GetAllValidators(nil) + validators, err := stakingContract.GetAllValidators(&bind.CallOpts{}) require.NoError(r, err) require.GreaterOrEqual(r, len(validators), 2) // shares are 0 for both validators at the start - sharesBeforeVal1, err := stakingContract.GetShares(nil, r.ZEVMAuth.From, validators[0].OperatorAddress) + sharesBeforeVal1, err := stakingContract.GetShares(&bind.CallOpts{}, r.ZEVMAuth.From, validators[0].OperatorAddress) require.NoError(r, err) require.Equal(r, int64(0), sharesBeforeVal1.Int64()) - sharesBeforeVal2, err := stakingContract.GetShares(nil, r.ZEVMAuth.From, validators[1].OperatorAddress) + sharesBeforeVal2, err := stakingContract.GetShares(&bind.CallOpts{}, r.ZEVMAuth.From, validators[1].OperatorAddress) require.NoError(r, err) require.Equal(r, int64(0), sharesBeforeVal2.Int64()) @@ -37,7 +42,7 @@ func TestPrecompilesStaking(r *runner.E2ERunner, args []string) { utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) // check shares are set to 3 - sharesAfterVal1, err := stakingContract.GetShares(nil, r.ZEVMAuth.From, validators[0].OperatorAddress) + sharesAfterVal1, err := stakingContract.GetShares(&bind.CallOpts{}, r.ZEVMAuth.From, validators[0].OperatorAddress) require.NoError(r, err) require.Equal(r, big.NewInt(3e18).String(), sharesAfterVal1.String()) @@ -47,12 +52,12 @@ func TestPrecompilesStaking(r *runner.E2ERunner, args []string) { utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) // check shares are set to 2 - sharesAfterVal1, err = stakingContract.GetShares(nil, r.ZEVMAuth.From, validators[0].OperatorAddress) + sharesAfterVal1, err = stakingContract.GetShares(&bind.CallOpts{}, r.ZEVMAuth.From, validators[0].OperatorAddress) require.NoError(r, err) require.Equal(r, big.NewInt(2e18).String(), sharesAfterVal1.String()) - // transfer 1 stake from validator1 to validator2 - tx, err = stakingContract.TransferStake( + // move 1 stake from validator1 to validator2 + tx, err = stakingContract.MoveStake( r.ZEVMAuth, r.ZEVMAuth.From, validators[0].OperatorAddress, @@ -64,11 +69,11 @@ func TestPrecompilesStaking(r *runner.E2ERunner, args []string) { utils.MustWaitForTxReceipt(r.Ctx, r.ZEVMClient, tx, r.Logger, r.ReceiptTimeout) // check shares for both validator1 and validator2 are 1 - sharesAfterVal1, err = stakingContract.GetShares(nil, r.ZEVMAuth.From, validators[0].OperatorAddress) + sharesAfterVal1, err = stakingContract.GetShares(&bind.CallOpts{}, r.ZEVMAuth.From, validators[0].OperatorAddress) require.NoError(r, err) require.Equal(r, big.NewInt(1e18).String(), sharesAfterVal1.String()) - sharesAfterVal2, err := stakingContract.GetShares(nil, r.ZEVMAuth.From, validators[1].OperatorAddress) + sharesAfterVal2, err := stakingContract.GetShares(&bind.CallOpts{}, r.ZEVMAuth.From, validators[1].OperatorAddress) require.NoError(r, err) require.Equal(r, big.NewInt(1e18).String(), sharesAfterVal2.String()) } diff --git a/precompiles/staking/IStaking.abi b/precompiles/staking/IStaking.abi index f6de61fb00..f8ee31e062 100644 --- a/precompiles/staking/IStaking.abi +++ b/precompiles/staking/IStaking.abi @@ -67,7 +67,12 @@ }, { "internalType": "string", - "name": "validator", + "name": "validatorSrc", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorDst", "type": "string" }, { @@ -76,12 +81,12 @@ "type": "uint256" } ], - "name": "stake", + "name": "moveStake", "outputs": [ { - "internalType": "bool", - "name": "success", - "type": "bool" + "internalType": "int64", + "name": "completionTime", + "type": "int64" } ], "stateMutability": "nonpayable", @@ -96,12 +101,7 @@ }, { "internalType": "string", - "name": "validatorSrc", - "type": "string" - }, - { - "internalType": "string", - "name": "validatorDst", + "name": "validator", "type": "string" }, { @@ -110,12 +110,12 @@ "type": "uint256" } ], - "name": "transferStake", + "name": "stake", "outputs": [ { - "internalType": "int64", - "name": "completionTime", - "type": "int64" + "internalType": "bool", + "name": "success", + "type": "bool" } ], "stateMutability": "nonpayable", diff --git a/precompiles/staking/IStaking.go b/precompiles/staking/IStaking.go index 1a2226b98c..ec3143f41f 100644 --- a/precompiles/staking/IStaking.go +++ b/precompiles/staking/IStaking.go @@ -39,7 +39,7 @@ type Validator struct { // IStakingMetaData contains all meta data concerning the IStaking contract. var IStakingMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"getAllValidators\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"operatorAddress\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"consensusPubKey\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"jailed\",\"type\":\"bool\"},{\"internalType\":\"enumBondStatus\",\"name\":\"bondStatus\",\"type\":\"uint8\"}],\"internalType\":\"structValidator[]\",\"name\":\"validators\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"validator\",\"type\":\"string\"}],\"name\":\"getShares\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"validator\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"stake\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"validatorSrc\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"validatorDst\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferStake\",\"outputs\":[{\"internalType\":\"int64\",\"name\":\"completionTime\",\"type\":\"int64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"validator\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"unstake\",\"outputs\":[{\"internalType\":\"int64\",\"name\":\"completionTime\",\"type\":\"int64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[],\"name\":\"getAllValidators\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"operatorAddress\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"consensusPubKey\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"jailed\",\"type\":\"bool\"},{\"internalType\":\"enumBondStatus\",\"name\":\"bondStatus\",\"type\":\"uint8\"}],\"internalType\":\"structValidator[]\",\"name\":\"validators\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"validator\",\"type\":\"string\"}],\"name\":\"getShares\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"validatorSrc\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"validatorDst\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"moveStake\",\"outputs\":[{\"internalType\":\"int64\",\"name\":\"completionTime\",\"type\":\"int64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"validator\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"stake\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"validator\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"unstake\",\"outputs\":[{\"internalType\":\"int64\",\"name\":\"completionTime\",\"type\":\"int64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", } // IStakingABI is the input ABI used to generate the binding from. @@ -250,6 +250,27 @@ func (_IStaking *IStakingCallerSession) GetShares(staker common.Address, validat return _IStaking.Contract.GetShares(&_IStaking.CallOpts, staker, validator) } +// MoveStake is a paid mutator transaction binding the contract method 0xd11a93d0. +// +// Solidity: function moveStake(address staker, string validatorSrc, string validatorDst, uint256 amount) returns(int64 completionTime) +func (_IStaking *IStakingTransactor) MoveStake(opts *bind.TransactOpts, staker common.Address, validatorSrc string, validatorDst string, amount *big.Int) (*types.Transaction, error) { + return _IStaking.contract.Transact(opts, "moveStake", staker, validatorSrc, validatorDst, amount) +} + +// MoveStake is a paid mutator transaction binding the contract method 0xd11a93d0. +// +// Solidity: function moveStake(address staker, string validatorSrc, string validatorDst, uint256 amount) returns(int64 completionTime) +func (_IStaking *IStakingSession) MoveStake(staker common.Address, validatorSrc string, validatorDst string, amount *big.Int) (*types.Transaction, error) { + return _IStaking.Contract.MoveStake(&_IStaking.TransactOpts, staker, validatorSrc, validatorDst, amount) +} + +// MoveStake is a paid mutator transaction binding the contract method 0xd11a93d0. +// +// Solidity: function moveStake(address staker, string validatorSrc, string validatorDst, uint256 amount) returns(int64 completionTime) +func (_IStaking *IStakingTransactorSession) MoveStake(staker common.Address, validatorSrc string, validatorDst string, amount *big.Int) (*types.Transaction, error) { + return _IStaking.Contract.MoveStake(&_IStaking.TransactOpts, staker, validatorSrc, validatorDst, amount) +} + // Stake is a paid mutator transaction binding the contract method 0x90b8436f. // // Solidity: function stake(address staker, string validator, uint256 amount) returns(bool success) @@ -271,27 +292,6 @@ func (_IStaking *IStakingTransactorSession) Stake(staker common.Address, validat return _IStaking.Contract.Stake(&_IStaking.TransactOpts, staker, validator, amount) } -// TransferStake is a paid mutator transaction binding the contract method 0x26d67892. -// -// Solidity: function transferStake(address staker, string validatorSrc, string validatorDst, uint256 amount) returns(int64 completionTime) -func (_IStaking *IStakingTransactor) TransferStake(opts *bind.TransactOpts, staker common.Address, validatorSrc string, validatorDst string, amount *big.Int) (*types.Transaction, error) { - return _IStaking.contract.Transact(opts, "transferStake", staker, validatorSrc, validatorDst, amount) -} - -// TransferStake is a paid mutator transaction binding the contract method 0x26d67892. -// -// Solidity: function transferStake(address staker, string validatorSrc, string validatorDst, uint256 amount) returns(int64 completionTime) -func (_IStaking *IStakingSession) TransferStake(staker common.Address, validatorSrc string, validatorDst string, amount *big.Int) (*types.Transaction, error) { - return _IStaking.Contract.TransferStake(&_IStaking.TransactOpts, staker, validatorSrc, validatorDst, amount) -} - -// TransferStake is a paid mutator transaction binding the contract method 0x26d67892. -// -// Solidity: function transferStake(address staker, string validatorSrc, string validatorDst, uint256 amount) returns(int64 completionTime) -func (_IStaking *IStakingTransactorSession) TransferStake(staker common.Address, validatorSrc string, validatorDst string, amount *big.Int) (*types.Transaction, error) { - return _IStaking.Contract.TransferStake(&_IStaking.TransactOpts, staker, validatorSrc, validatorDst, amount) -} - // Unstake is a paid mutator transaction binding the contract method 0x57c6ea3e. // // Solidity: function unstake(address staker, string validator, uint256 amount) returns(int64 completionTime) diff --git a/precompiles/staking/IStaking.json b/precompiles/staking/IStaking.json index 87e1599ce9..bd89798977 100644 --- a/precompiles/staking/IStaking.json +++ b/precompiles/staking/IStaking.json @@ -68,7 +68,12 @@ }, { "internalType": "string", - "name": "validator", + "name": "validatorSrc", + "type": "string" + }, + { + "internalType": "string", + "name": "validatorDst", "type": "string" }, { @@ -77,12 +82,12 @@ "type": "uint256" } ], - "name": "stake", + "name": "moveStake", "outputs": [ { - "internalType": "bool", - "name": "success", - "type": "bool" + "internalType": "int64", + "name": "completionTime", + "type": "int64" } ], "stateMutability": "nonpayable", @@ -97,12 +102,7 @@ }, { "internalType": "string", - "name": "validatorSrc", - "type": "string" - }, - { - "internalType": "string", - "name": "validatorDst", + "name": "validator", "type": "string" }, { @@ -111,12 +111,12 @@ "type": "uint256" } ], - "name": "transferStake", + "name": "stake", "outputs": [ { - "internalType": "int64", - "name": "completionTime", - "type": "int64" + "internalType": "bool", + "name": "success", + "type": "bool" } ], "stateMutability": "nonpayable", diff --git a/precompiles/staking/IStaking.sol b/precompiles/staking/IStaking.sol index 9cd26a9889..7924b296c0 100644 --- a/precompiles/staking/IStaking.sol +++ b/precompiles/staking/IStaking.sol @@ -47,13 +47,13 @@ interface IStaking { uint256 amount ) external returns (int64 completionTime); - /// @notice Transfer coins from validatorSrc to validatorDst + /// @notice Move coins from validatorSrc to validatorDst /// @param staker Staker address /// @param validatorSrc Validator from address /// @param validatorDst Validator to address /// @param amount Coins amount - /// @return completionTime Time when staket transfer is done - function transferStake( + /// @return completionTime Time when stake move is done + function moveStake( address staker, string memory validatorSrc, string memory validatorDst, diff --git a/precompiles/staking/staking.go b/precompiles/staking/staking.go index 6d72658e6c..c0e6649ae6 100644 --- a/precompiles/staking/staking.go +++ b/precompiles/staking/staking.go @@ -19,9 +19,9 @@ import ( const ( // write - StakeMethodName = "stake" - UnstakeMethodName = "unstake" - TransferStakeMethodName = "transferStake" + StakeMethodName = "stake" + UnstakeMethodName = "unstake" + MoveStakeMethodName = "moveStake" // read GetAllValidatorsMethodName = "getAllValidators" @@ -55,7 +55,7 @@ func initABI() { GasRequiredByMethod[methodID] = 10000 case UnstakeMethodName: GasRequiredByMethod[methodID] = 10000 - case TransferStakeMethodName: + case MoveStakeMethodName: GasRequiredByMethod[methodID] = 10000 case GetAllValidatorsMethodName: GasRequiredByMethod[methodID] = 0 @@ -126,7 +126,7 @@ func (c *Contract) GetAllValidators( ) ([]byte, error) { validators := c.stakingKeeper.GetAllValidators(ctx) - validatorsRes := []Validator{} + validatorsRes := make([]Validator, len(validators)) for _, v := range validators { validatorsRes = append(validatorsRes, Validator{ OperatorAddress: v.OperatorAddress, @@ -291,7 +291,7 @@ func (c *Contract) Unstake( return method.Outputs.Pack(res.GetCompletionTime().UTC().Unix()) } -func (c *Contract) TransferStake( +func (c *Contract) MoveStake( ctx sdk.Context, origin common.Address, method *abi.Method, @@ -409,10 +409,10 @@ func (c *Contract) Run(evm *vm.EVM, contract *vm.Contract, _ bool) ([]byte, erro return nil, err } return res, nil - case TransferStakeMethodName: + case MoveStakeMethodName: var res []byte execErr := stateDB.ExecuteNativeAction(contract.Address(), nil, func(ctx sdk.Context) error { - res, err = c.TransferStake(ctx, evm.Origin, method, args) + res, err = c.MoveStake(ctx, evm.Origin, method, args) return err }) if execErr != nil { diff --git a/precompiles/staking/staking_test.go b/precompiles/staking/staking_test.go index 462e815774..6ae2f1fc3f 100644 --- a/precompiles/staking/staking_test.go +++ b/precompiles/staking/staking_test.go @@ -62,8 +62,8 @@ func Test_IStakingContract(t *testing.T) { require.NotNil(t, abi.Methods[UnstakeMethodName], "unstake method should be present in the ABI") require.NotNil( t, - abi.Methods[TransferStakeMethodName], - "transferStake method should be present in the ABI", + abi.Methods[MoveStakeMethodName], + "moveStake method should be present in the ABI", ) require.NotNil( @@ -78,7 +78,9 @@ func Test_IStakingContract(t *testing.T) { var method [4]byte t.Run("stake", func(t *testing.T) { + // ACT stake := contract.RequiredGas(abi.Methods[StakeMethodName].ID) + // ASSERT copy(method[:], abi.Methods[StakeMethodName].ID[:4]) baseCost := uint64(len(method)) * gasConfig.WriteCostPerByte require.Equal( @@ -92,7 +94,9 @@ func Test_IStakingContract(t *testing.T) { }) t.Run("unstake", func(t *testing.T) { + // ACT unstake := contract.RequiredGas(abi.Methods[UnstakeMethodName].ID) + // ASSERT copy(method[:], abi.Methods[UnstakeMethodName].ID[:4]) baseCost := uint64(len(method)) * gasConfig.WriteCostPerByte require.Equal( @@ -105,22 +109,26 @@ func Test_IStakingContract(t *testing.T) { ) }) - t.Run("transferStake", func(t *testing.T) { - transferStake := contract.RequiredGas(abi.Methods[TransferStakeMethodName].ID) - copy(method[:], abi.Methods[TransferStakeMethodName].ID[:4]) + t.Run("moveStake", func(t *testing.T) { + // ACT + moveStake := contract.RequiredGas(abi.Methods[MoveStakeMethodName].ID) + // ASSERT + copy(method[:], abi.Methods[MoveStakeMethodName].ID[:4]) baseCost := uint64(len(method)) * gasConfig.WriteCostPerByte require.Equal( t, GasRequiredByMethod[method]+baseCost, - transferStake, - "transferStake method should require %d gas, got %d", + moveStake, + "moveStake method should require %d gas, got %d", GasRequiredByMethod[method]+baseCost, - transferStake, + moveStake, ) }) t.Run("getAllValidators", func(t *testing.T) { + // ACT getAllValidators := contract.RequiredGas(abi.Methods[GetAllValidatorsMethodName].ID) + // ASSERT copy(method[:], abi.Methods[GetAllValidatorsMethodName].ID[:4]) baseCost := uint64(len(method)) * gasConfig.ReadCostPerByte require.Equal( @@ -134,7 +142,9 @@ func Test_IStakingContract(t *testing.T) { }) t.Run("getShares", func(t *testing.T) { + // ACT getShares := contract.RequiredGas(abi.Methods[GetSharesMethodName].ID) + // ASSERT copy(method[:], abi.Methods[GetSharesMethodName].ID[:4]) baseCost := uint64(len(method)) * gasConfig.ReadCostPerByte require.Equal( @@ -148,8 +158,11 @@ func Test_IStakingContract(t *testing.T) { }) t.Run("invalid method", func(t *testing.T) { + // ARRANGE invalidMethodBytes := []byte("invalidMethod") + // ACT gasInvalidMethod := contract.RequiredGas(invalidMethodBytes) + // ASSERT require.Equal( t, uint64(0), @@ -185,6 +198,7 @@ func Test_Stake(t *testing.T) { methodID := abi.Methods[StakeMethodName] t.Run("should fail if validator doesn't exist", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) @@ -200,11 +214,15 @@ func Test_Stake(t *testing.T) { args := []interface{}{stakerEthAddr, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt()} + // ACT _, err = contract.Stake(ctx, stakerAddr, &methodID, args) + + // ASSERT require.Error(t, err) }) t.Run("should stake", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -221,11 +239,15 @@ func Test_Stake(t *testing.T) { args := []interface{}{stakerEthAddr, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt()} + // ACT _, err = contract.Stake(ctx, stakerAddr, &methodID, args) + + // ASSERT require.NoError(t, err) }) t.Run("should fail if origin is not staker", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -243,11 +265,15 @@ func Test_Stake(t *testing.T) { args := []interface{}{originEthAddr, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt()} + // ACT _, err = contract.Stake(ctx, stakerAddr, &methodID, args) + + // ASSERT require.ErrorContains(t, err, "origin is not staker address") }) t.Run("should fail if staking fails", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -260,11 +286,15 @@ func Test_Stake(t *testing.T) { args := []interface{}{stakerEthAddr, validator.OperatorAddress, int64(42)} + // ACT _, err := contract.Stake(ctx, stakerAddr, &methodID, args) + + // ASSERT require.Error(t, err) }) t.Run("should fail if wrong args amount", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -281,11 +311,15 @@ func Test_Stake(t *testing.T) { args := []interface{}{stakerEthAddr, validator.OperatorAddress} + // ACT _, err = contract.Stake(ctx, stakerAddr, &methodID, args) + + // ASSERT require.Error(t, err) }) t.Run("should fail if staker is not eth addr", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -301,11 +335,15 @@ func Test_Stake(t *testing.T) { args := []interface{}{staker, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt()} + // ACT _, err = contract.Stake(ctx, stakerAddr, &methodID, args) + + // ASSERT require.Error(t, err) }) t.Run("should fail if validator is not valid string", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -322,11 +360,15 @@ func Test_Stake(t *testing.T) { args := []interface{}{stakerEthAddr, 42, coins.AmountOf(config.BaseDenom).BigInt()} + // ACT _, err = contract.Stake(ctx, stakerAddr, &methodID, args) + + // ASSERT require.Error(t, err) }) t.Run("should fail if amount is not int64", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -343,7 +385,10 @@ func Test_Stake(t *testing.T) { args := []interface{}{stakerEthAddr, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).Uint64()} + // ACT _, err = contract.Stake(ctx, stakerAddr, &methodID, args) + + // ASSERT require.Error(t, err) }) } @@ -353,6 +398,7 @@ func Test_Unstake(t *testing.T) { methodID := abi.Methods[UnstakeMethodName] t.Run("should fail if validator doesn't exist", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) @@ -368,11 +414,15 @@ func Test_Unstake(t *testing.T) { args := []interface{}{stakerEthAddr, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt()} + // ACT _, err = contract.Unstake(ctx, stakerAddr, &methodID, args) + + // ASSERT require.Error(t, err) }) t.Run("should unstake", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -394,11 +444,15 @@ func Test_Unstake(t *testing.T) { _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, args) require.NoError(t, err) + // ACT _, err = contract.Unstake(ctx, stakerAddr, &methodID, args) + + // ASSERT require.NoError(t, err) }) t.Run("should fail if origin is not staker", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -422,11 +476,15 @@ func Test_Unstake(t *testing.T) { originEthAddr := common.BytesToAddress(sample.Bech32AccAddress().Bytes()) + // ACT _, err = contract.Unstake(ctx, originEthAddr, &methodID, args) + + // ASSERT require.ErrorContains(t, err, "origin is not staker address") }) t.Run("should fail if no previous staking", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -443,11 +501,15 @@ func Test_Unstake(t *testing.T) { args := []interface{}{stakerEthAddr, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt()} + // ACT _, err = contract.Unstake(ctx, stakerAddr, &methodID, args) + + // ASSERT require.Error(t, err) }) t.Run("should fail if wrong args amount", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -464,11 +526,15 @@ func Test_Unstake(t *testing.T) { args := []interface{}{stakerEthAddr, validator.OperatorAddress} + // ACT _, err = contract.Unstake(ctx, stakerAddr, &methodID, args) + + // ASSERT require.Error(t, err) }) t.Run("should fail if staker is not eth addr", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -484,11 +550,15 @@ func Test_Unstake(t *testing.T) { args := []interface{}{staker, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt()} + // ACT _, err = contract.Unstake(ctx, stakerAddr, &methodID, args) + + // ASSERT require.Error(t, err) }) t.Run("should fail if validator is not valid string", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -505,11 +575,15 @@ func Test_Unstake(t *testing.T) { args := []interface{}{stakerEthAddr, 42, coins.AmountOf(config.BaseDenom).BigInt()} + // ACT _, err = contract.Unstake(ctx, stakerAddr, &methodID, args) + + // ASSERT require.Error(t, err) }) t.Run("should fail if amount is not int64", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -526,16 +600,20 @@ func Test_Unstake(t *testing.T) { args := []interface{}{stakerEthAddr, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).Uint64()} + // ACT _, err = contract.Unstake(ctx, stakerAddr, &methodID, args) + + // ASSERT require.Error(t, err) }) } -func Test_TransferStake(t *testing.T) { +func Test_MoveStake(t *testing.T) { ctx, contract, abi, sdkKeepers := setup(t) - methodID := abi.Methods[TransferStakeMethodName] + methodID := abi.Methods[MoveStakeMethodName] t.Run("should fail if validator dest doesn't exist", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validatorSrc := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validatorSrc) @@ -562,18 +640,22 @@ func Test_TransferStake(t *testing.T) { _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, argsStake) require.NoError(t, err) - argsTransferStake := []interface{}{ + argsMoveStake := []interface{}{ stakerEthAddr, validatorSrc.OperatorAddress, validatorDest.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt(), } - _, err = contract.TransferStake(ctx, stakerAddr, &methodID, argsTransferStake) + // ACT + _, err = contract.MoveStake(ctx, stakerAddr, &methodID, argsMoveStake) + + // ASSERT require.Error(t, err) }) - t.Run("should transfer stake", func(t *testing.T) { + t.Run("should move stake", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validatorSrc := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validatorSrc) @@ -601,19 +683,23 @@ func Test_TransferStake(t *testing.T) { _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, argsStake) require.NoError(t, err) - argsTransferStake := []interface{}{ + argsMoveStake := []interface{}{ stakerEthAddr, validatorSrc.OperatorAddress, validatorDest.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt(), } - // transfer stake to validator dest - _, err = contract.TransferStake(ctx, stakerAddr, &methodID, argsTransferStake) + // ACT + // move stake to validator dest + _, err = contract.MoveStake(ctx, stakerAddr, &methodID, argsMoveStake) + + // ASSERT require.NoError(t, err) }) t.Run("should fail if staker is invalid arg", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validatorSrc := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validatorSrc) @@ -641,18 +727,22 @@ func Test_TransferStake(t *testing.T) { _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, argsStake) require.NoError(t, err) - argsTransferStake := []interface{}{ + argsMoveStake := []interface{}{ 42, validatorSrc.OperatorAddress, validatorDest.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt(), } - _, err = contract.TransferStake(ctx, stakerAddr, &methodID, argsTransferStake) + // ACT + _, err = contract.MoveStake(ctx, stakerAddr, &methodID, argsMoveStake) + + // ASSERT require.Error(t, err) }) t.Run("should fail if validator src is invalid arg", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validatorSrc := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validatorSrc) @@ -680,18 +770,22 @@ func Test_TransferStake(t *testing.T) { _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, argsStake) require.NoError(t, err) - argsTransferStake := []interface{}{ + argsMoveStake := []interface{}{ stakerEthAddr, 42, validatorDest.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt(), } - _, err = contract.TransferStake(ctx, stakerAddr, &methodID, argsTransferStake) + // ACT + _, err = contract.MoveStake(ctx, stakerAddr, &methodID, argsMoveStake) + + // ASSERT require.Error(t, err) }) t.Run("should fail if validator dest is invalid arg", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validatorSrc := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validatorSrc) @@ -719,18 +813,22 @@ func Test_TransferStake(t *testing.T) { _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, argsStake) require.NoError(t, err) - argsTransferStake := []interface{}{ + argsMoveStake := []interface{}{ stakerEthAddr, validatorSrc.OperatorAddress, 42, coins.AmountOf(config.BaseDenom).BigInt(), } - _, err = contract.TransferStake(ctx, stakerAddr, &methodID, argsTransferStake) + // ACT + _, err = contract.MoveStake(ctx, stakerAddr, &methodID, argsMoveStake) + + // ASSERT require.Error(t, err) }) t.Run("should fail if amount is invalid arg", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validatorSrc := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validatorSrc) @@ -758,18 +856,22 @@ func Test_TransferStake(t *testing.T) { _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, argsStake) require.NoError(t, err) - argsTransferStake := []interface{}{ + argsMoveStake := []interface{}{ stakerEthAddr, validatorSrc.OperatorAddress, validatorDest.OperatorAddress, coins.AmountOf(config.BaseDenom).Uint64(), } - _, err = contract.TransferStake(ctx, stakerAddr, &methodID, argsTransferStake) + // ACT + _, err = contract.MoveStake(ctx, stakerAddr, &methodID, argsMoveStake) + + // ASSERT require.Error(t, err) }) t.Run("should fail if wrong args amount", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validatorSrc := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validatorSrc) @@ -797,13 +899,17 @@ func Test_TransferStake(t *testing.T) { _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, argsStake) require.NoError(t, err) - argsTransferStake := []interface{}{stakerEthAddr, validatorSrc.OperatorAddress, validatorDest.OperatorAddress} + argsMoveStake := []interface{}{stakerEthAddr, validatorSrc.OperatorAddress, validatorDest.OperatorAddress} - _, err = contract.TransferStake(ctx, stakerAddr, &methodID, argsTransferStake) + // ACT + _, err = contract.MoveStake(ctx, stakerAddr, &methodID, argsMoveStake) + + // ASSERT require.Error(t, err) }) t.Run("should fail if origin is not staker", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validatorSrc := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validatorSrc) @@ -831,7 +937,7 @@ func Test_TransferStake(t *testing.T) { _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, argsStake) require.NoError(t, err) - argsTransferStake := []interface{}{ + argsMoveStake := []interface{}{ stakerEthAddr, validatorSrc.OperatorAddress, validatorDest.OperatorAddress, @@ -839,7 +945,11 @@ func Test_TransferStake(t *testing.T) { } originEthAddr := common.BytesToAddress(sample.Bech32AccAddress().Bytes()) - _, err = contract.TransferStake(ctx, originEthAddr, &methodID, argsTransferStake) + + // ACT + _, err = contract.MoveStake(ctx, originEthAddr, &methodID, argsMoveStake) + + // ASSERT require.ErrorContains(t, err, "origin is not staker") }) } @@ -849,7 +959,10 @@ func Test_GetAllValidators(t *testing.T) { methodID := abi.Methods[GetAllValidatorsMethodName] t.Run("should return empty array if validators not set", func(t *testing.T) { + // ACT validators, err := contract.GetAllValidators(ctx, &methodID) + + // ASSERT require.NoError(t, err) res, err := methodID.Outputs.Unpack(validators) @@ -859,11 +972,15 @@ func Test_GetAllValidators(t *testing.T) { }) t.Run("should return validators if set", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) + // ACT validators, err := contract.GetAllValidators(ctx, &methodID) + + // ASSERT require.NoError(t, err) res, err := methodID.Outputs.Unpack(validators) @@ -878,6 +995,7 @@ func Test_GetShares(t *testing.T) { methodID := abi.Methods[GetSharesMethodName] t.Run("should return stakes", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) sdkKeepers.StakingKeeper.SetValidator(ctx, validator) @@ -895,9 +1013,12 @@ func Test_GetShares(t *testing.T) { stakeArgs := []interface{}{stakerEthAddr, validator.OperatorAddress, coins.AmountOf(config.BaseDenom).BigInt()} stakeMethodID := abi.Methods[StakeMethodName] + + // ACT _, err = contract.Stake(ctx, stakerAddr, &stakeMethodID, stakeArgs) require.NoError(t, err) + // ASSERT args := []interface{}{stakerEthAddr, validator.OperatorAddress} stakes, err := contract.GetShares(ctx, &methodID, args) require.NoError(t, err) @@ -912,29 +1033,41 @@ func Test_GetShares(t *testing.T) { }) t.Run("should fail if wrong args amount", func(t *testing.T) { + // ARRANGE staker := sample.Bech32AccAddress() stakerEthAddr := common.BytesToAddress(staker.Bytes()) - args := []interface{}{stakerEthAddr} + + // ACT _, err := contract.GetShares(ctx, &methodID, args) + + // ASSERT require.Error(t, err) }) t.Run("should fail if invalid staker arg", func(t *testing.T) { + // ARRANGE r := rand.New(rand.NewSource(42)) validator := sample.Validator(t, r) - args := []interface{}{42, validator.OperatorAddress} + + // ACT _, err := contract.GetShares(ctx, &methodID, args) + + // ASSERT require.Error(t, err) }) t.Run("should fail if invalid val address", func(t *testing.T) { + // ARRANGE staker := sample.Bech32AccAddress() stakerEthAddr := common.BytesToAddress(staker.Bytes()) - args := []interface{}{stakerEthAddr, staker.String()} + + // ACT _, err := contract.GetShares(ctx, &methodID, args) + + // ASSERT require.Error(t, err) }) }