From f06d075bd36c931246a11c81fc2d9060df32c4ac Mon Sep 17 00:00:00 2001 From: salaheldinsoliman Date: Tue, 25 Jun 2024 16:54:42 +0200 Subject: [PATCH] add test in proper directory Signed-off-by: salaheldinsoliman --- packages/evm/evmtest/GetBalance.abi | 1 + packages/evm/evmtest/GetBalance.bin | 1 + packages/evm/evmtest/GetBalance.sol | 27 +++++++ packages/evm/evmtest/contracts.go | 9 +++ .../vm/core/evm/evmtest/contractInstance.go | 17 +++++ packages/vm/core/evm/evmtest/evm_test.go | 75 +++++++++++++++++++ 6 files changed, 130 insertions(+) create mode 100644 packages/evm/evmtest/GetBalance.abi create mode 100644 packages/evm/evmtest/GetBalance.bin create mode 100644 packages/evm/evmtest/GetBalance.sol diff --git a/packages/evm/evmtest/GetBalance.abi b/packages/evm/evmtest/GetBalance.abi new file mode 100644 index 0000000000..7c76c6cbbf --- /dev/null +++ b/packages/evm/evmtest/GetBalance.abi @@ -0,0 +1 @@ +[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"agentID","type":"bytes"}],"name":"GotAgentID","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"baseBalance","type":"uint64"}],"name":"GotBaseBalance","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"nftBalance","type":"uint256"}],"name":"GotNFTIDs","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"nativeTokenBalance","type":"uint256"}],"name":"GotNativeTokenBalance","type":"event"},{"inputs":[{"internalType":"bytes","name":"nativeTokenID","type":"bytes"}],"name":"getBalance","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/packages/evm/evmtest/GetBalance.bin b/packages/evm/evmtest/GetBalance.bin new file mode 100644 index 0000000000..dcf08c7827 --- /dev/null +++ b/packages/evm/evmtest/GetBalance.bin @@ -0,0 +1 @@ +608060405234801561000f575f80fd5b506108ef8061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063d0fc35011461002d575b5f80fd5b610047600480360381019061004291906104c5565b610049565b005b5f73107400000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f31317496040518163ffffffff1660e01b81526004015f60405180830381865afa1580156100a6573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906100ce91906105ff565b90507f28b3d377892d8db500fb9a9bbd4731605ca2a642c3c62a7e64d47b7d42024368815f01516040516101029190610698565b60405180910390a15f73107400000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663b019204f836040518263ffffffff1660e01b81526004016101589190610727565b602060405180830381865afa158015610173573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101979190610784565b90507f23ce6861f26687742455d6955fcd53a5587ecf279e37422d0cd9636e2a2a9f7f816040516101c891906107be565b60405180910390a15f60405180602001604052808581525090505f73107400000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ef43e40d83866040518363ffffffff1660e01b81526004016102329291906107fe565b602060405180830381865afa15801561024d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102719190610866565b90507fab4abdf0d66655ed9c7e1ee2f2aff1d43dbdc0736a3e7078c2be95bcf3800575816040516102a291906108a0565b60405180910390a15f73107400000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630d90ec7b866040518263ffffffff1660e01b81526004016102f89190610727565b602060405180830381865afa158015610313573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103379190610866565b90507f52c249d568f18754049ea99591153f1f0ad8c7ab03a3bcdcf8454bc274e541018160405161036891906108a0565b60405180910390a1505050505050565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6103d782610391565b810181811067ffffffffffffffff821117156103f6576103f56103a1565b5b80604052505050565b5f610408610378565b905061041482826103ce565b919050565b5f67ffffffffffffffff821115610433576104326103a1565b5b61043c82610391565b9050602081019050919050565b828183375f83830152505050565b5f61046961046484610419565b6103ff565b9050828152602081018484840111156104855761048461038d565b5b610490848285610449565b509392505050565b5f82601f8301126104ac576104ab610389565b5b81356104bc848260208601610457565b91505092915050565b5f602082840312156104da576104d9610381565b5b5f82013567ffffffffffffffff8111156104f7576104f6610385565b5b61050384828501610498565b91505092915050565b5f80fd5b5f80fd5b5f5b83811015610531578082015181840152602081019050610516565b5f8484015250505050565b5f61054e61054984610419565b6103ff565b90508281526020810184848401111561056a5761056961038d565b5b610575848285610514565b509392505050565b5f82601f83011261059157610590610389565b5b81516105a184826020860161053c565b91505092915050565b5f602082840312156105bf576105be61050c565b5b6105c960206103ff565b90505f82015167ffffffffffffffff8111156105e8576105e7610510565b5b6105f48482850161057d565b5f8301525092915050565b5f6020828403121561061457610613610381565b5b5f82015167ffffffffffffffff81111561063157610630610385565b5b61063d848285016105aa565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f61066a82610646565b6106748185610650565b9350610684818560208601610514565b61068d81610391565b840191505092915050565b5f6020820190508181035f8301526106b08184610660565b905092915050565b5f82825260208201905092915050565b5f6106d282610646565b6106dc81856106b8565b93506106ec818560208601610514565b6106f581610391565b840191505092915050565b5f602083015f8301518482035f86015261071a82826106c8565b9150508091505092915050565b5f6020820190508181035f83015261073f8184610700565b905092915050565b5f67ffffffffffffffff82169050919050565b61076381610747565b811461076d575f80fd5b50565b5f8151905061077e8161075a565b92915050565b5f6020828403121561079957610798610381565b5b5f6107a684828501610770565b91505092915050565b6107b881610747565b82525050565b5f6020820190506107d15f8301846107af565b92915050565b5f602083015f8301518482035f8601526107f182826106c8565b9150508091505092915050565b5f6040820190508181035f83015261081681856107d7565b9050818103602083015261082a8184610700565b90509392505050565b5f819050919050565b61084581610833565b811461084f575f80fd5b50565b5f815190506108608161083c565b92915050565b5f6020828403121561087b5761087a610381565b5b5f61088884828501610852565b91505092915050565b61089a81610833565b82525050565b5f6020820190506108b35f830184610891565b9291505056fea264697066735822122090eb26ecd9fcc4785bf94129a00cd83e3e9f7eee6f59bc51191d4984ac66195064736f6c63430008140033 \ No newline at end of file diff --git a/packages/evm/evmtest/GetBalance.sol b/packages/evm/evmtest/GetBalance.sol new file mode 100644 index 0000000000..88e1d0b98a --- /dev/null +++ b/packages/evm/evmtest/GetBalance.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "@iscmagic/ISC.sol"; + +contract GetBalance { + event GotAgentID(bytes agentID); + event GotBaseBalance(uint64 baseBalance); + event GotNativeTokenBalance(uint256 nativeTokenBalance); + event GotNFTIDs(uint256 nftBalance); + + function getBalance(bytes memory nativeTokenID) public { + ISCAgentID memory agentID = ISC.sandbox.getSenderAccount(); + emit GotAgentID(agentID.data); + + uint64 baseBalance = ISC.accounts.getL2BalanceBaseTokens(agentID); + emit GotBaseBalance(baseBalance); + + NativeTokenID memory id = NativeTokenID({ data: nativeTokenID}); + uint256 nativeTokens = ISC.accounts.getL2BalanceNativeTokens(id, agentID); + emit GotNativeTokenBalance(nativeTokens); + + uint256 nfts = ISC.accounts.getL2NFTAmount(agentID); + emit GotNFTIDs(nfts); + } +} \ No newline at end of file diff --git a/packages/evm/evmtest/contracts.go b/packages/evm/evmtest/contracts.go index 805eb11443..88f7929ead 100644 --- a/packages/evm/evmtest/contracts.go +++ b/packages/evm/evmtest/contracts.go @@ -54,6 +54,15 @@ var ( ISCTestContractBytecode = common.FromHex(strings.TrimSpace(iscTestContractBytecodeHex)) ) +//go:generate sh -c "solc --abi --bin --overwrite @iscmagic=`realpath ../../vm/core/evm/iscmagic` GetBalance.sol -o ." +var ( + //go:embed GetBalance.abi + GetBalanceContractABI string + //go:embed GetBalance.bin + GetBalanceContractBytecodeHex string + GetBalanceContractBytecode = common.FromHex(strings.TrimSpace(GetBalanceContractBytecodeHex)) +) + //go:generate solc --abi --bin --overwrite Fibonacci.sol -o . var ( //go:embed Fibonacci.abi diff --git a/packages/vm/core/evm/evmtest/contractInstance.go b/packages/vm/core/evm/evmtest/contractInstance.go index 53652d5d69..aa120efcf9 100644 --- a/packages/vm/core/evm/evmtest/contractInstance.go +++ b/packages/vm/core/evm/evmtest/contractInstance.go @@ -4,6 +4,7 @@ import ( "crypto/ecdsa" "fmt" "math/big" + "slices" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" @@ -152,6 +153,22 @@ func (e *EVMContractInstance) CallFnExpectEvent(opts []ethCallOptions, eventName return res } +// If a Solidity function emits multiple events, this function will return the first event that matches the given eventName +func (e *EVMContractInstance) CallFnExpectMultipleEvents(opts []ethCallOptions, eventName string, v interface{}, fnName string, args ...interface{}) CallFnResult { + res, err := e.CallFn(opts, fnName, args...) + require.NoError(e.chain.t, err) + require.Equal(e.chain.t, types.ReceiptStatusSuccessful, res.EVMReceipt.Status) + //require.Len(e.chain.t, res.EVMReceipt.Logs, len(eventNames)) + topic := e.abi.Events[eventName].ID + for _, log := range res.EVMReceipt.Logs { + if slices.Contains(log.Topics, topic) { + err = e.abi.UnpackIntoInterface(v, eventName, log.Data) + } + require.NoError(e.chain.t, err) + } + return res +} + func (e *EVMContractInstance) callView(fnName string, args []interface{}, v interface{}, blockNumberOrHash ...rpc.BlockNumberOrHash) error { e.chain.t.Logf("callView: %s %+v", fnName, args) callArguments, err := e.abi.Pack(fnName, args...) diff --git a/packages/vm/core/evm/evmtest/evm_test.go b/packages/vm/core/evm/evmtest/evm_test.go index 69ae8c0687..c01d43b96d 100644 --- a/packages/vm/core/evm/evmtest/evm_test.go +++ b/packages/vm/core/evm/evmtest/evm_test.go @@ -23,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/rpc" "github.com/samber/lo" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" iotago "github.com/iotaledger/iota.go/v3" @@ -2690,3 +2691,77 @@ func TestDisableMagicWrap(t *testing.T) { envWithMagicWrap := InitEVM(t, true) require.NotNil(t, envWithMagicWrap.getCode(envWithMagicWrap.ERC20BaseTokens(nil).address)) } + +func TestGetBalancea(t *testing.T) { + + env := InitEVMWithSolo(t, solo.New(t), true) + privateKey, deployer := env.Chain.NewEthereumAccountWithL2Funds() + + instance := env.DeployContract(privateKey, evmtest.GetBalanceContractABI, evmtest.GetBalanceContractBytecode) + + // create a new native token on L1 + foundry, tokenId, err := env.Chain.NewNativeTokenParams(100000000000000).CreateFoundry() + require.NoError(t, err) + // the token id in bytes, used to call the contract + nativeTokenIdBytes := isc.NativeTokenIDToBytes(tokenId) + + // mint some native tokens to the chain originator + err = env.Chain.MintTokens(foundry, 10000000, env.Chain.OriginatorPrivateKey) + require.NoError(t, err) + + // get the agentId of the contract deployer + senderAgentId := isc.NewEthereumAddressAgentID(env.Chain.ChainID, deployer) + + // test 1 + // get the actual base balance of the contract deployer + // and compare it with the balance returned by the contract + balance, _ := env.Chain.EVM().Balance(deployer, nil) + decimals := env.Chain.EVM().BaseToken().Decimals + var value uint64 + instance.CallFnExpectMultipleEvents(nil, "GotBaseBalance", &value, "getBalance", nativeTokenIdBytes) + real := util.BaseTokensDecimalsToEthereumDecimals(value, decimals) + assert.Equal(t, balance, real) + + // test 2 + // get the agnetId of the contract deployer + // and compare it with the agentId returned by the contract + var agent_id []byte + instance.CallFnExpectMultipleEvents(nil, "GotAgentID", &agent_id, "getBalance", nativeTokenIdBytes) + assert.Equal(t, senderAgentId.Bytes(), agent_id) + + // test 3 + // get the native token balance of the contract deployer + // It should be 0, because the contract deployer has not received any native tokens yet + nativeBalance := new(big.Int) + instance.CallFnExpectMultipleEvents(nil, "GotNativeTokenBalance", &nativeBalance, "getBalance", nativeTokenIdBytes) + assert.Equal(t, int64(0), nativeBalance.Int64()) + + // test 4 + // send some native tokens to the contract deployer + // and check if the balance returned by the contract is correct + err = env.Chain.SendFromL2ToL2AccountNativeTokens(tokenId, senderAgentId, 100000, env.Chain.OriginatorPrivateKey) + require.NoError(t, err) + instance.CallFnExpectMultipleEvents(nil, "GotNativeTokenBalance", &nativeBalance, "getBalance", nativeTokenIdBytes) + assert.Equal(t, int64(100000), nativeBalance.Int64()) + + // test 5 + // mint an NFToken to the contract deployer + // and check if the balance returned by the contract is correct + mockMetaData := []byte("sesa") + nfti, info, err := env.Chain.Env.MintNFTL1(env.Chain.OriginatorPrivateKey, env.Chain.OriginatorAddress, mockMetaData) + require.NoError(t, err) + env.Chain.MustDepositNFT(nfti, env.Chain.OriginatorAgentID, env.Chain.OriginatorPrivateKey) + + transfer := isc.NewEmptyAssets() + transfer.AddNFTs(info.NFTID) + + // send the NFT to the contract deployer + err = env.Chain.SendFromL2ToL2Account(transfer, senderAgentId, env.Chain.OriginatorPrivateKey) + require.NoError(t, err) + + // get the NFT balance of the contract deployer + nftBalance := new(big.Int) + instance.CallFnExpectMultipleEvents(nil, "GotNFTIDs", &nftBalance, "getBalance", nativeTokenIdBytes) + assert.Equal(t, int64(1), nftBalance.Int64()) + +}