diff --git a/app/app_parallel_test.go b/app/app_parallel_test.go index e3de02f593..b2563d8319 100644 --- a/app/app_parallel_test.go +++ b/app/app_parallel_test.go @@ -1,11 +1,15 @@ package app_test import ( + "encoding/hex" "encoding/json" + "fmt" + "io/ioutil" "math/big" "reflect" "strings" "testing" + "time" "github.com/ethereum/go-ethereum/accounts/abi" ethcmn "github.com/ethereum/go-ethereum/common" @@ -25,6 +29,16 @@ import ( tmtypes "github.com/okex/exchain/libs/tendermint/types" evmtypes "github.com/okex/exchain/x/evm/types" tokentypes "github.com/okex/exchain/x/token/types" + wasmtypes "github.com/okex/exchain/x/wasm/types" +) + +var ( + testPrecompileCodeA = "60806040526101006000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561005257600080fd5b50610b76806100626000396000f3fe60806040526004361061004a5760003560e01c80635b3082c21461004f57806363de1b5d1461007f5780636bbb9b13146100af5780638381f58a146100df578063be2b0ac21461010a575b600080fd5b610069600480360381019061006491906106cc565b610147565b60405161007691906108ba565b60405180910390f35b61009960048036038101906100949190610670565b610161565b6040516100a69190610898565b60405180910390f35b6100c960048036038101906100c49190610744565b610314565b6040516100d69190610898565b60405180910390f35b3480156100eb57600080fd5b506100f46104ca565b6040516101019190610913565b60405180910390f35b34801561011657600080fd5b50610131600480360381019061012c91906105de565b6104d0565b60405161013e91906108ba565b60405180910390f35b606060405180602001604052806000815250905092915050565b60606001805461017191906109c7565b60018190555060008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1634866040516024016101c391906108ba565b6040516020818303038152906040527fbe2b0ac2000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161024d9190610881565b60006040518083038185875af1925050503d806000811461028a576040519150601f19603f3d011682016040523d82523d6000602084013e61028f565b606091505b509150915083156102f557816102a457600080fd5b6000818060200190518101906102ba9190610627565b90507fe390e3d6b4766bc311796e6b5ce75dd6d51f0cb55cea58be963a5e7972ade65c816040516102eb91906108ba565b60405180910390a1505b6001805461030391906109c7565b600181905550809250505092915050565b60606001805461032491906109c7565b60018190555060008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163487876040516024016103789291906108dc565b6040516020818303038152906040527f5b3082c2000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516104029190610881565b60006040518083038185875af1925050503d806000811461043f576040519150601f19603f3d011682016040523d82523d6000602084013e610444565b606091505b509150915083156104aa578161045957600080fd5b60008180602001905181019061046f9190610627565b90507fe390e3d6b4766bc311796e6b5ce75dd6d51f0cb55cea58be963a5e7972ade65c816040516104a091906108ba565b60405180910390a1505b600180546104b891906109c7565b60018190555080925050509392505050565b60015481565b6060604051806020016040528060008152509050919050565b60006104fc6104f784610953565b61092e565b90508281526020810184848401111561051857610517610b09565b5b610523848285610a33565b509392505050565b600061053e61053984610953565b61092e565b90508281526020810184848401111561055a57610559610b09565b5b610565848285610a42565b509392505050565b60008135905061057c81610b29565b92915050565b600082601f83011261059757610596610b04565b5b81356105a78482602086016104e9565b91505092915050565b600082601f8301126105c5576105c4610b04565b5b81516105d584826020860161052b565b91505092915050565b6000602082840312156105f4576105f3610b13565b5b600082013567ffffffffffffffff81111561061257610611610b0e565b5b61061e84828501610582565b91505092915050565b60006020828403121561063d5761063c610b13565b5b600082015167ffffffffffffffff81111561065b5761065a610b0e565b5b610667848285016105b0565b91505092915050565b6000806040838503121561068757610686610b13565b5b600083013567ffffffffffffffff8111156106a5576106a4610b0e565b5b6106b185828601610582565b92505060206106c28582860161056d565b9150509250929050565b600080604083850312156106e3576106e2610b13565b5b600083013567ffffffffffffffff81111561070157610700610b0e565b5b61070d85828601610582565b925050602083013567ffffffffffffffff81111561072e5761072d610b0e565b5b61073a85828601610582565b9150509250929050565b60008060006060848603121561075d5761075c610b13565b5b600084013567ffffffffffffffff81111561077b5761077a610b0e565b5b61078786828701610582565b935050602084013567ffffffffffffffff8111156107a8576107a7610b0e565b5b6107b486828701610582565b92505060406107c58682870161056d565b9150509250925092565b60006107da82610984565b6107e4818561099a565b93506107f4818560208601610a42565b6107fd81610b18565b840191505092915050565b600061081382610984565b61081d81856109ab565b935061082d818560208601610a42565b80840191505092915050565b60006108448261098f565b61084e81856109b6565b935061085e818560208601610a42565b61086781610b18565b840191505092915050565b61087b81610a29565b82525050565b600061088d8284610808565b915081905092915050565b600060208201905081810360008301526108b281846107cf565b905092915050565b600060208201905081810360008301526108d48184610839565b905092915050565b600060408201905081810360008301526108f68185610839565b9050818103602083015261090a8184610839565b90509392505050565b60006020820190506109286000830184610872565b92915050565b6000610938610949565b90506109448282610a75565b919050565b6000604051905090565b600067ffffffffffffffff82111561096e5761096d610ad5565b5b61097782610b18565b9050602081019050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b60006109d282610a29565b91506109dd83610a29565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610a1257610a11610aa6565b5b828201905092915050565b60008115159050919050565b6000819050919050565b82818337600083830152505050565b60005b83811015610a60578082015181840152602081019050610a45565b83811115610a6f576000848401525b50505050565b610a7e82610b18565b810181811067ffffffffffffffff82111715610a9d57610a9c610ad5565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b610b3281610a1d565b8114610b3d57600080fd5b5056fea264697066735822122099b3fbd7a2bf1822c7f366e7e6685aa6801d09d9932acbf59c0687cae6df69da64736f6c63430008070033" + + contractJson = `{"abi":[{"inputs":[],"name":"add","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"retrieve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"}],"name":"store","outputs":[],"stateMutability":"nonpayable","type":"function"}],"bin":"608060405234801561001057600080fd5b50610205806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80632e64cec1146100465780634f2be91f146100645780636057361d1461006e575b600080fd5b61004e61008a565b60405161005b91906100d1565b60405180910390f35b61006c610093565b005b6100886004803603810190610083919061011d565b6100ae565b005b60008054905090565b60016000808282546100a59190610179565b92505081905550565b8060008190555050565b6000819050919050565b6100cb816100b8565b82525050565b60006020820190506100e660008301846100c2565b92915050565b600080fd5b6100fa816100b8565b811461010557600080fd5b50565b600081359050610117816100f1565b92915050565b600060208284031215610133576101326100ec565b5b600061014184828501610108565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610184826100b8565b915061018f836100b8565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156101c4576101c361014a565b5b82820190509291505056fea2646970667358221220742b7232e733bee3592cb9e558bdae3fbd0006bcbdba76abc47b6020744037b364736f6c634300080a0033"}` + + testPrecompileABIAJson = "{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"wasmAddr\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"data\",\"type\":\"string\"}],\"name\":\"callToWasm\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"response\",\"type\":\"string\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"wasmAddr\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"msgData\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"requireASuccess\",\"type\":\"bool\"}],\"name\":\"callWasm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"data\",\"type\":\"string\"}],\"name\":\"pushLog\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"msgData\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"requireASuccess\",\"type\":\"bool\"}],\"name\":\"queryWasm\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"data\",\"type\":\"string\"}],\"name\":\"queryToWasm\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"response\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"bin\":\"60806040526101006000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561005257600080fd5b50610b76806100626000396000f3fe60806040526004361061004a5760003560e01c80635b3082c21461004f57806363de1b5d1461007f5780636bbb9b13146100af5780638381f58a146100df578063be2b0ac21461010a575b600080fd5b610069600480360381019061006491906106cc565b610147565b60405161007691906108ba565b60405180910390f35b61009960048036038101906100949190610670565b610161565b6040516100a69190610898565b60405180910390f35b6100c960048036038101906100c49190610744565b610314565b6040516100d69190610898565b60405180910390f35b3480156100eb57600080fd5b506100f46104ca565b6040516101019190610913565b60405180910390f35b34801561011657600080fd5b50610131600480360381019061012c91906105de565b6104d0565b60405161013e91906108ba565b60405180910390f35b606060405180602001604052806000815250905092915050565b60606001805461017191906109c7565b60018190555060008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1634866040516024016101c391906108ba565b6040516020818303038152906040527fbe2b0ac2000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161024d9190610881565b60006040518083038185875af1925050503d806000811461028a576040519150601f19603f3d011682016040523d82523d6000602084013e61028f565b606091505b509150915083156102f557816102a457600080fd5b6000818060200190518101906102ba9190610627565b90507fe390e3d6b4766bc311796e6b5ce75dd6d51f0cb55cea58be963a5e7972ade65c816040516102eb91906108ba565b60405180910390a1505b6001805461030391906109c7565b600181905550809250505092915050565b60606001805461032491906109c7565b60018190555060008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163487876040516024016103789291906108dc565b6040516020818303038152906040527f5b3082c2000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516104029190610881565b60006040518083038185875af1925050503d806000811461043f576040519150601f19603f3d011682016040523d82523d6000602084013e610444565b606091505b509150915083156104aa578161045957600080fd5b60008180602001905181019061046f9190610627565b90507fe390e3d6b4766bc311796e6b5ce75dd6d51f0cb55cea58be963a5e7972ade65c816040516104a091906108ba565b60405180910390a1505b600180546104b891906109c7565b60018190555080925050509392505050565b60015481565b6060604051806020016040528060008152509050919050565b60006104fc6104f784610953565b61092e565b90508281526020810184848401111561051857610517610b09565b5b610523848285610a33565b509392505050565b600061053e61053984610953565b61092e565b90508281526020810184848401111561055a57610559610b09565b5b610565848285610a42565b509392505050565b60008135905061057c81610b29565b92915050565b600082601f83011261059757610596610b04565b5b81356105a78482602086016104e9565b91505092915050565b600082601f8301126105c5576105c4610b04565b5b81516105d584826020860161052b565b91505092915050565b6000602082840312156105f4576105f3610b13565b5b600082013567ffffffffffffffff81111561061257610611610b0e565b5b61061e84828501610582565b91505092915050565b60006020828403121561063d5761063c610b13565b5b600082015167ffffffffffffffff81111561065b5761065a610b0e565b5b610667848285016105b0565b91505092915050565b6000806040838503121561068757610686610b13565b5b600083013567ffffffffffffffff8111156106a5576106a4610b0e565b5b6106b185828601610582565b92505060206106c28582860161056d565b9150509250929050565b600080604083850312156106e3576106e2610b13565b5b600083013567ffffffffffffffff81111561070157610700610b0e565b5b61070d85828601610582565b925050602083013567ffffffffffffffff81111561072e5761072d610b0e565b5b61073a85828601610582565b9150509250929050565b60008060006060848603121561075d5761075c610b13565b5b600084013567ffffffffffffffff81111561077b5761077a610b0e565b5b61078786828701610582565b935050602084013567ffffffffffffffff8111156107a8576107a7610b0e565b5b6107b486828701610582565b92505060406107c58682870161056d565b9150509250925092565b60006107da82610984565b6107e4818561099a565b93506107f4818560208601610a42565b6107fd81610b18565b840191505092915050565b600061081382610984565b61081d81856109ab565b935061082d818560208601610a42565b80840191505092915050565b60006108448261098f565b61084e81856109b6565b935061085e818560208601610a42565b61086781610b18565b840191505092915050565b61087b81610a29565b82525050565b600061088d8284610808565b915081905092915050565b600060208201905081810360008301526108b281846107cf565b905092915050565b600060208201905081810360008301526108d48184610839565b905092915050565b600060408201905081810360008301526108f68185610839565b9050818103602083015261090a8184610839565b90509392505050565b60006020820190506109286000830184610872565b92915050565b6000610938610949565b90506109448282610a75565b919050565b6000604051905090565b600067ffffffffffffffff82111561096e5761096d610ad5565b5b61097782610b18565b9050602081019050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b60006109d282610a29565b91506109dd83610a29565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610a1257610a11610aa6565b5b828201905092915050565b60008115159050919050565b6000819050919050565b82818337600083830152505050565b60005b83811015610a60578082015181840152602081019050610a45565b83811115610a6f576000848401525b50505050565b610a7e82610b18565b810181811067ffffffffffffffff82111715610a9d57610a9c610ad5565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b610b3281610a1d565b8114610b3d57600080fd5b5056fea264697066735822122099b3fbd7a2bf1822c7f366e7e6685aa6801d09d9932acbf59c0687cae6df69da64736f6c63430008070033\"}" + callWasmMsgFormat = "{\"transfer\":{\"amount\":\"%d\",\"recipient\":\"%s\"}}" ) type Env struct { @@ -43,6 +57,11 @@ type Chain struct { chainIdStr string chainIdInt *big.Int ContractAddr []byte + + VMBContractA ethcmn.Address + VMBWasmContract sdk.WasmAddress + + timeYear int } func NewChain(env *Env) *Chain { @@ -59,6 +78,7 @@ func NewChain(env *Env) *Chain { chain.num = make([]uint64, 10) chain.chainIdStr = "ethermint-3" chain.chainIdInt = big.NewInt(3) + chain.timeYear = 2022 // initialize account genAccs := make([]authexported.GenesisAccount, 0) for i := 0; i < 10; i++ { @@ -79,6 +99,7 @@ func NewChain(env *Env) *Chain { chain.app = app.SetupWithGenesisAccounts(false, genAccs, app.WithChainId(chain.chainIdStr)) chain.codec = chain.app.Codec() + chain.app.WasmKeeper.SetParams(chain.Ctx(), wasmtypes.TestParams()) params := evmtypes.DefaultParams() params.EnableCreate = true params.EnableCall = true @@ -205,7 +226,9 @@ func createAnteErrTokenSendTx(t *testing.T, chain *Chain, i int) []byte { } func runTxs(chain *Chain, rawTxs [][]byte, isParallel bool) []*abci.ResponseDeliverTx { - header := abci.Header{Height: chain.app.LastBlockHeight() + 1, ChainID: chain.chainIdStr} + timeValue := fmt.Sprintf("%d-04-11 13:33:37", chain.timeYear+1) + testTime, _ := time.Parse("2006-01-02 15:04:05", timeValue) + header := abci.Header{Height: chain.app.LastBlockHeight() + 1, ChainID: chain.chainIdStr, Time: testTime} chain.app.BaseApp.BeginBlock(abci.RequestBeginBlock{Header: header}) var ret []*abci.ResponseDeliverTx if isParallel { @@ -234,6 +257,10 @@ func TestParallelTxs(t *testing.T) { env.addr[i] = addr } chainA, chainB := NewChain(env), NewChain(env) + + VMBPrecompileSetup(t, chainA) + VMBPrecompileSetup(t, chainB) + DeployContractAndGetContractAddress(t, chainA) DeployContractAndGetContractAddress(t, chainB) @@ -990,6 +1017,22 @@ func TestParallelTxs(t *testing.T) { }, []uint32{0, 3, 61034, 11, 0}, }, + { + "1 evm tx, 1 callWasm vmb tx, 1 Failed cosmos tx, 1 Failed evm contract txs,and 1 evm contract tx", + func(t *testing.T, chain *Chain, isParallel bool) ([]*abci.ResponseDeliverTx, []byte, []byte) { + var rawTxs [][]byte + rawTxs = append(rawTxs, createEthTx(t, chain, 0)) + rawTxs = append(rawTxs, callWasmAtContractA(t, chain, 1)) + rawTxs = append(rawTxs, createFailedTokenSendTx(t, chain, 2)) + //one group 2txs + rawTxs = append(rawTxs, callContractFailed(t, chain, 3)) + rawTxs = append(rawTxs, callContract(t, chain, 4)) + ret := runTxs(chain, rawTxs, isParallel) + + return ret, resultHash(ret), chain.app.BaseApp.LastCommitID().Hash + }, + []uint32{0, 0, 61034, 11, 0}, + }, } for _, tc := range testCases { @@ -1009,26 +1052,26 @@ func resultHash(txs []*abci.ResponseDeliverTx) []byte { return results.Hash() } -//contract Storage { -//uint256 number; -///** +// contract Storage { +// uint256 number; +// /** // * @dev Store value in variable // * @param num value to store // */ -//function store(uint256 num) public { -//number = num; -//} -//function add() public { -//number += 1; -//} -///** +// function store(uint256 num) public { +// number = num; +// } +// function add() public { +// number += 1; +// } +// /** // * @dev Return value // * @return value of 'number' // */ -//function retrieve() public view returns (uint256){ -//return number; -//} -//} +// function retrieve() public view returns (uint256){ +// return number; +// } +// } var abiStr = `[{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"}],"name":"add","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"retrieve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"}],"name":"store","outputs":[],"stateMutability":"nonpayable","type":"function"}]` func deployContract(t *testing.T, chain *Chain, i int) []byte { @@ -1048,16 +1091,14 @@ func deployContract(t *testing.T, chain *Chain, i int) []byte { return rawTx } -var contractJson = `{"abi":[{"inputs":[],"name":"add","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"retrieve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"}],"name":"store","outputs":[],"stateMutability":"nonpayable","type":"function"}],"bin":"608060405234801561001057600080fd5b50610205806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80632e64cec1146100465780634f2be91f146100645780636057361d1461006e575b600080fd5b61004e61008a565b60405161005b91906100d1565b60405180910390f35b61006c610093565b005b6100886004803603810190610083919061011d565b6100ae565b005b60008054905090565b60016000808282546100a59190610179565b92505081905550565b8060008190555050565b6000819050919050565b6100cb816100b8565b82525050565b60006020820190506100e660008301846100c2565b92915050565b600080fd5b6100fa816100b8565b811461010557600080fd5b50565b600081359050610117816100f1565b92915050565b600060208284031215610133576101326100ec565b5b600061014184828501610108565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610184826100b8565b915061018f836100b8565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156101c4576101c361014a565b5b82820190509291505056fea2646970667358221220742b7232e733bee3592cb9e558bdae3fbd0006bcbdba76abc47b6020744037b364736f6c634300080a0033"}` - type CompiledContract struct { ABI abi.ABI Bin string } -func UnmarshalContract(t *testing.T) *CompiledContract { +func UnmarshalContract(t *testing.T, cJson string) *CompiledContract { cc := new(CompiledContract) - err := json.Unmarshal([]byte(contractJson), cc) + err := json.Unmarshal([]byte(cJson), cc) require.NoError(t, err) return cc } @@ -1067,7 +1108,7 @@ func callContract(t *testing.T, chain *Chain, i int) []byte { gasPrice := big.NewInt(100000000) //to := ethcmn.HexToAddress(chain.priv[i].PubKey().Address().String()) to := ethcmn.BytesToAddress(chain.ContractAddr) - cc := UnmarshalContract(t) + cc := UnmarshalContract(t, contractJson) data, err := cc.ABI.Pack("add") require.NoError(t, err) msg := evmtypes.NewMsgEthereumTx(chain.seq[i], &to, big.NewInt(0), gasLimit, gasPrice, data) @@ -1079,12 +1120,30 @@ func callContract(t *testing.T, chain *Chain, i int) []byte { return rawTx } +func callWasmAtContractA(t *testing.T, chain *Chain, i int) []byte { + gasLimit := uint64(30000000) + gasPrice := big.NewInt(100000000) + + to := ethcmn.BytesToAddress(chain.VMBWasmContract.Bytes()) + cc := UnmarshalContract(t, testPrecompileABIAJson) + wasmCallData := fmt.Sprintf(callWasmMsgFormat, 10, chain.addr[i].String()) + data, err := cc.ABI.Pack("callWasm", chain.VMBWasmContract.String(), hex.EncodeToString([]byte(wasmCallData)), true) + require.NoError(t, err) + msg := evmtypes.NewMsgEthereumTx(chain.seq[i], &to, big.NewInt(0), gasLimit, gasPrice, data) + err = msg.Sign(big.NewInt(3), chain.priv[i].ToECDSA()) + require.NoError(t, err) + chain.seq[i]++ + rawTx, err := rlp.EncodeToBytes(&msg) + require.NoError(t, err) + return rawTx +} + func callContractFailed(t *testing.T, chain *Chain, i int) []byte { gasLimit := uint64(1) gasPrice := big.NewInt(100000000) //to := ethcmn.HexToAddress(chain.priv[i].PubKey().Address().String()) to := ethcmn.BytesToAddress(chain.ContractAddr) - cc := UnmarshalContract(t) + cc := UnmarshalContract(t, contractJson) data, err := cc.ABI.Pack("add") require.NoError(t, err) msg := evmtypes.NewMsgEthereumTx(chain.seq[i], &to, big.NewInt(0), gasLimit, gasPrice, data) @@ -1101,7 +1160,7 @@ func callContractAnteErr(t *testing.T, chain *Chain, i int) []byte { gasPrice := big.NewInt(100000000) //to := ethcmn.HexToAddress(chain.priv[i].PubKey().Address().String()) to := ethcmn.BytesToAddress(chain.ContractAddr) - cc := UnmarshalContract(t) + cc := UnmarshalContract(t, contractJson) data, err := cc.ABI.Pack("add") require.NoError(t, err) msg := evmtypes.NewMsgEthereumTx(chain.seq[i]+1, &to, big.NewInt(0), gasLimit, gasPrice, data) @@ -1117,3 +1176,34 @@ func checkCodes(t *testing.T, title string, resp []*abci.ResponseDeliverTx, code require.True(t, resp[i].Code == code, "title: %s, expect code: %d, but %d! tx index: %d", title, code, resp[i].Code, i) } } + +func VMBPrecompileSetup(t *testing.T, chain *Chain) { + timeValue := fmt.Sprintf("%d-04-11 13:33:37", chain.timeYear+1) + testTime, _ := time.Parse("2006-01-02 15:04:05", timeValue) + header := abci.Header{Height: chain.app.LastBlockHeight() + 1, ChainID: chain.chainIdStr, Time: testTime} + chain.app.BaseApp.BeginBlock(abci.RequestBeginBlock{Header: header}) + chain.VMBContractA = vmbDeployEvmContract(t, chain, testPrecompileCodeA) + initMsg := []byte(fmt.Sprintf("{\"decimals\":10,\"initial_balances\":[{\"address\":\"%s\",\"amount\":\"100000000\"}],\"name\":\"my test token\", \"symbol\":\"MTT\"}", chain.addr[0].String())) + chain.VMBWasmContract = vmbDeployWasmContract(t, chain, "precompile.wasm", initMsg) + chain.app.BaseApp.EndBlock(abci.RequestEndBlock{}) + chain.app.BaseApp.Commit(abci.RequestCommit{}) +} + +func vmbDeployEvmContract(t *testing.T, chain *Chain, code string) ethcmn.Address { + freeCallBytecode := ethcmn.Hex2Bytes(code) + _, contract, err := chain.app.VMBridgeKeeper.CallEvm(chain.Ctx(), ethcmn.BytesToAddress(chain.addr[0]), nil, big.NewInt(0), freeCallBytecode) + require.NoError(t, err) + chain.seq[0]++ + return contract.ContractAddress +} + +func vmbDeployWasmContract(t *testing.T, chain *Chain, filename string, initMsg []byte) sdk.WasmAddress { + wasmcode, err := ioutil.ReadFile(fmt.Sprintf("./testdata/%s", filename)) + require.NoError(t, err) + codeid, err := chain.app.WasmPermissionKeeper.Create(chain.Ctx(), sdk.AccToAWasmddress(chain.addr[0]), wasmcode, nil) + require.NoError(t, err) + //initMsg := []byte(fmt.Sprintf("{\"decimals\":10,\"initial_balances\":[{\"address\":\"%s\",\"amount\":\"100000000\"}],\"name\":\"my test token\", \"symbol\":\"MTT\"}", suite.addr.String())) + contract, _, err := chain.app.WasmPermissionKeeper.Instantiate(chain.Ctx(), codeid, sdk.AccToAWasmddress(chain.addr[0]), sdk.AccToAWasmddress(chain.addr[0]), initMsg, "label", sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)}) + require.NoError(t, err) + return contract +} diff --git a/app/data/wasm/cache/modules/v3-wasmer1/4926b4112508882c2889fcd39841aabaaebf515dad5c956e88fb3c2a624528ee b/app/data/wasm/cache/modules/v3-wasmer1/4926b4112508882c2889fcd39841aabaaebf515dad5c956e88fb3c2a624528ee new file mode 100644 index 0000000000..911cee9baf Binary files /dev/null and b/app/data/wasm/cache/modules/v3-wasmer1/4926b4112508882c2889fcd39841aabaaebf515dad5c956e88fb3c2a624528ee differ diff --git a/app/data/wasm/state/wasm/4926b4112508882c2889fcd39841aabaaebf515dad5c956e88fb3c2a624528ee b/app/data/wasm/state/wasm/4926b4112508882c2889fcd39841aabaaebf515dad5c956e88fb3c2a624528ee new file mode 100644 index 0000000000..c79e6e9f42 Binary files /dev/null and b/app/data/wasm/state/wasm/4926b4112508882c2889fcd39841aabaaebf515dad5c956e88fb3c2a624528ee differ diff --git a/app/test_helpers.go b/app/test_helpers.go index b5eecfa31e..1603e44f7d 100644 --- a/app/test_helpers.go +++ b/app/test_helpers.go @@ -1,6 +1,8 @@ package app import ( + "time" + "github.com/spf13/viper" "github.com/okex/exchain/libs/cosmos-sdk/codec" @@ -79,11 +81,13 @@ func SetupWithGenesisAccounts(isCheckTx bool, genAccs []authexported.GenesisAcco } // Initialize the chain + testTime, _ := time.Parse("2006-01-02 15:04:05", "2017-04-11 13:33:37") app.InitChain( abci.RequestInitChain{ Validators: []abci.ValidatorUpdate{}, AppStateBytes: stateBytes, ChainId: setupOption.chainId, + Time: testTime, }, ) diff --git a/app/testdata/cw20.wasm b/app/testdata/cw20.wasm new file mode 100644 index 0000000000..9ad8edb813 Binary files /dev/null and b/app/testdata/cw20.wasm differ diff --git a/app/testdata/freecall.sol b/app/testdata/freecall.sol new file mode 100644 index 0000000000..dee445d3a6 --- /dev/null +++ b/app/testdata/freecall.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.18; +// pragma solidity >=0.7.0 <0.9.0; + + +contract FreeCall { + address public constant moduleAddress = + address(0x1033796B018B2bf0Fc9CB88c0793b2F275eDB624); + + event __OKCCallToWasm(string wasmAddr, uint256 value, string data); + + function callByWasm(string memory callerWasmAddr,string memory data) public payable returns (string memory response) { + string memory temp1 = strConcat("callByWasm return: ",callerWasmAddr); + string memory temp2 = strConcat(temp1," ---data: "); + string memory temp3 = strConcat(temp2,data); + return temp3; + } + + + function callToWasm(string memory wasmAddr, uint256 value, string memory data) public returns (bool success){ + emit __OKCCallToWasm(wasmAddr,value,data); + return true; + } + + + function strConcat(string memory _a, string memory _b) internal returns (string memory){ + bytes memory _ba = bytes(_a); + bytes memory _bb = bytes(_b); + string memory ret = new string(_ba.length + _bb.length); + bytes memory bret = bytes(ret); + uint k = 0; + for (uint i = 0; i < _ba.length; i++) { + bret[k++] = _ba[i]; + } + for (uint i = 0; i < _bb.length; i++) { + bret[k++] = _bb[i]; + } + return string(ret); + } +} diff --git a/app/testdata/freecall.wasm b/app/testdata/freecall.wasm new file mode 100644 index 0000000000..8cf65f6b87 Binary files /dev/null and b/app/testdata/freecall.wasm differ diff --git a/app/testdata/precompile.sol b/app/testdata/precompile.sol new file mode 100644 index 0000000000..9d8aa653ab --- /dev/null +++ b/app/testdata/precompile.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.7.0 <0.9.0; + +contract ContractA { + + address precomplieContarct = 0x0000000000000000000000000000000000000100; + uint256 public number; + event pushLog(string data); + + function callWasm(string memory wasmAddr, string memory msgData,bool requireASuccess) public payable returns (bytes memory response){ + number = number + 1; + (bool success, bytes memory data) = precomplieContarct.call{value: msg.value} ( + abi.encodeWithSignature("callToWasm(string,string)", wasmAddr,msgData) + ); + if (requireASuccess) { + require(success); + string memory res = abi.decode(data,(string)); + emit pushLog(res); + } + number = number + 1; + return data; + } + + function queryWasm(string memory msgData,bool requireASuccess) public payable returns (bytes memory response){ + number = number + 1; + (bool success, bytes memory data) = precomplieContarct.call{value: msg.value} ( + abi.encodeWithSignature("queryToWasm(string)",msgData) + ); + if (requireASuccess) { + require(success); + string memory res = abi.decode(data,(string)); + emit pushLog(res); + } + number = number + 1; + return data; + } + + function callToWasm(string memory wasmAddr, string memory data) public payable returns (string memory response) { + return ""; + } + + function queryToWasm(string memory data) public view returns (string memory response) { + return ""; + } +} + +contract ContractB { + uint256 public number; + + function callWasm(address contractA ,string memory wasmAddr, string memory msgData, bool requireASuccess,bool requireBSuccess) public payable returns (bytes memory response){ + number = number + 1; + (bool success, bytes memory data) = contractA.call{value: msg.value} ( + abi.encodeWithSignature("callWasm(string,string,bool)", wasmAddr,msgData,requireASuccess) + ); + number = number + 1; + if (requireBSuccess) { + require(success); + } + return data; + } + + function queryWasm(address contractA , string memory msgData, bool requireASuccess,bool requireBSuccess) public payable returns (bytes memory response){ + number = number + 1; + (bool success, bytes memory data) = contractA.call{value: msg.value} ( + abi.encodeWithSignature("queryWasm(string,bool)",msgData,requireASuccess) + ); + number = number + 1; + if (requireBSuccess) { + require(success); + } + return data; + } +} diff --git a/app/testdata/precompile.wasm b/app/testdata/precompile.wasm new file mode 100644 index 0000000000..c79e6e9f42 Binary files /dev/null and b/app/testdata/precompile.wasm differ diff --git a/app/testdata/testerc20.sol b/app/testdata/testerc20.sol new file mode 100644 index 0000000000..04117671b6 --- /dev/null +++ b/app/testdata/testerc20.sol @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.7; + +contract Exchange is ERC20 { + address public constant moduleAddress = + address(0xc63cf6c8E1f3DF41085E9d8Af49584dae1432b4f); + + string public wasmContractAddress = "ex14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s6fqu27"; + + event __OKCSendToWasm(string wasmAddr, string recipient, uint256 amount); + + function initialize(string memory denom_, uint8 decimals_) public { + __ERC20_init(denom_, denom_, decimals_); + } + + function native_denom() public view returns (string memory) { + return symbol(); + } + + function updatewasmContractAddress(string memory addr) public { + wasmContractAddress = addr; + } + + function mint(address recipient,uint256 amount) public { + _mint(recipient, amount); + } + + + function mintERC20(string calldata caller, address recipient,uint256 amount) public returns (bool) { + require(msg.sender == moduleAddress); + require(keccak256(abi.encodePacked(caller)) == keccak256(abi.encodePacked(wasmContractAddress))); + _mint(recipient, amount); + return true; + } + + + // send an "amount" of the contract token to recipient on wasm + function send_to_wasm(string memory recipient,string memory wasmContract , uint256 amount) public { + _burn(msg.sender, amount); + emit __OKCSendToWasm(wasmContract,recipient, amount); + } +} + +contract ERC20 { + bool private initialized; + + string private _name; + string private _symbol; + uint8 private _decimals; + uint256 private _totalSupply; + + mapping(address => uint256) private _balances; + mapping(address => mapping(address => uint256)) private _allowances; + + event Transfer(address indexed from, address indexed to, uint256 value); + event Approval( + address indexed owner, + address indexed spender, + uint256 value + ); + + function __ERC20_init( + string memory name_, + string memory symbol_, + uint8 decimals_ + ) internal { + require(!initialized, "ERC20: already initialized;"); + initialized = true; + + _name = name_; + _symbol = symbol_; + _decimals = decimals_; + } + + function name() public view virtual returns (string memory) { + return _name; + } + + function symbol() public view virtual returns (string memory) { + return _symbol; + } + + function decimals() public view virtual returns (uint8) { + return _decimals; + } + + function totalSupply() public view virtual returns (uint256) { + return _totalSupply; + } + + function balanceOf(address account) public view virtual returns (uint256) { + return _balances[account]; + } + + function transfer(address to, uint256 amount) + public + virtual + returns (bool) + { + address owner = msg.sender; + _transfer(owner, to, amount); + return true; + } + + function allowance(address owner, address spender) + public + view + virtual + returns (uint256) + { + return _allowances[owner][spender]; + } + + function approve(address spender, uint256 amount) + public + virtual + returns (bool) + { + address owner = msg.sender; + _approve(owner, spender, amount); + return true; + } + + function transferFrom( + address from, + address to, + uint256 amount + ) public virtual returns (bool) { + address spender = msg.sender; + _spendAllowance(from, spender, amount); + _transfer(from, to, amount); + return true; + } + + function increaseAllowance(address spender, uint256 addedValue) + public + virtual + returns (bool) + { + address owner = msg.sender; + _approve(owner, spender, _allowances[owner][spender] + addedValue); + return true; + } + + function decreaseAllowance(address spender, uint256 subtractedValue) + public + virtual + returns (bool) + { + address owner = msg.sender; + uint256 currentAllowance = _allowances[owner][spender]; + require( + currentAllowance >= subtractedValue, + "ERC20: decreased allowance below zero" + ); + unchecked { + _approve(owner, spender, currentAllowance - subtractedValue); + } + + return true; + } + + function _transfer( + address from, + address to, + uint256 amount + ) internal virtual { + require(from != address(0), "ERC20: transfer from the zero address"); + require(to != address(0), "ERC20: transfer to the zero address"); + + uint256 fromBalance = _balances[from]; + require( + fromBalance >= amount, + "ERC20: transfer amount exceeds balance" + ); + unchecked { + _balances[from] = fromBalance - amount; + } + _balances[to] += amount; + + emit Transfer(from, to, amount); + } + + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + } + + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + } + + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + function _spendAllowance( + address owner, + address spender, + uint256 amount + ) internal virtual { + uint256 currentAllowance = allowance(owner, spender); + if (currentAllowance != type(uint256).max) { + require( + currentAllowance >= amount, + "ERC20: insufficient allowance" + ); + unchecked { + _approve(owner, spender, currentAllowance - amount); + } + } + } +}