diff --git a/Makefile b/Makefile index 368314c3d2..6e48fdc995 100644 --- a/Makefile +++ b/Makefile @@ -37,6 +37,7 @@ wasm: compile-solidity: cd packages/vm/core/evm/iscmagic && go generate cd packages/evm/evmtest && go generate + cd packages/evm/evmtest/wiki_how_tos && go generate build-cli: cd tools/wasp-cli && go mod tidy && go build -ldflags $(BUILD_LD_FLAGS) -tags ${WASP_CLI_TAGS} -o ../../ diff --git a/packages/evm/evmtest/wiki_how_tos/GetBalance.abi b/packages/evm/evmtest/wiki_how_tos/GetBalance.abi new file mode 100644 index 0000000000..bf80089cdf --- /dev/null +++ b/packages/evm/evmtest/wiki_how_tos/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":[],"name":"getAgentID","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getBalanceBaseTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getBalanceNFTs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"nativeTokenID","type":"bytes"}],"name":"getBalanceNativeTokens","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/packages/evm/evmtest/wiki_how_tos/GetBalance.bin b/packages/evm/evmtest/wiki_how_tos/GetBalance.bin new file mode 100644 index 0000000000..a1349b6c02 --- /dev/null +++ b/packages/evm/evmtest/wiki_how_tos/GetBalance.bin @@ -0,0 +1 @@ +6080604052348015600e575f80fd5b50610ab28061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061004a575f3560e01c806319a5506a1461004e57806341d9834c1461005857806390cdadcd14610074578063cdfd0a661461007e575b5f80fd5b610056610088565b005b610072600480360381019061006d91906106a2565b6101d9565b005b61007c610340565b005b610086610404565b005b5f73107400000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f31317496040518163ffffffff1660e01b81526004015f60405180830381865afa1580156100e5573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061010d91906107c2565b90505f73107400000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630d90ec7b836040518263ffffffff1660e01b815260040161015d9190610882565b602060405180830381865afa158015610178573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061019c91906108d5565b90507f52c249d568f18754049ea99591153f1f0ad8c7ab03a3bcdcf8454bc274e54101816040516101cd919061090f565b60405180910390a15050565b5f73107400000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f31317496040518163ffffffff1660e01b81526004015f60405180830381865afa158015610236573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061025e91906107c2565b90505f60405180602001604052808481525090505f73107400000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ef43e40d83856040518363ffffffff1660e01b81526004016102c292919061094f565b602060405180830381865afa1580156102dd573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061030191906108d5565b90507fab4abdf0d66655ed9c7e1ee2f2aff1d43dbdc0736a3e7078c2be95bcf380057581604051610332919061090f565b60405180910390a150505050565b5f73107400000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f31317496040518163ffffffff1660e01b81526004015f60405180830381865afa15801561039d573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906103c591906107c2565b90507f28b3d377892d8db500fb9a9bbd4731605ca2a642c3c62a7e64d47b7d42024368815f01516040516103f991906109cc565b60405180910390a150565b5f73107400000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f31317496040518163ffffffff1660e01b81526004015f60405180830381865afa158015610461573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061048991906107c2565b90505f73107400000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663b019204f836040518263ffffffff1660e01b81526004016104d99190610882565b602060405180830381865afa1580156104f4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105189190610a29565b90507f23ce6861f26687742455d6955fcd53a5587ecf279e37422d0cd9636e2a2a9f7f816040516105499190610a63565b60405180910390a15050565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6105b48261056e565b810181811067ffffffffffffffff821117156105d3576105d261057e565b5b80604052505050565b5f6105e5610555565b90506105f182826105ab565b919050565b5f67ffffffffffffffff8211156106105761060f61057e565b5b6106198261056e565b9050602081019050919050565b828183375f83830152505050565b5f610646610641846105f6565b6105dc565b9050828152602081018484840111156106625761066161056a565b5b61066d848285610626565b509392505050565b5f82601f83011261068957610688610566565b5b8135610699848260208601610634565b91505092915050565b5f602082840312156106b7576106b661055e565b5b5f82013567ffffffffffffffff8111156106d4576106d3610562565b5b6106e084828501610675565b91505092915050565b5f80fd5b5f80fd5b8281835e5f83830152505050565b5f61071161070c846105f6565b6105dc565b90508281526020810184848401111561072d5761072c61056a565b5b6107388482856106f1565b509392505050565b5f82601f83011261075457610753610566565b5b81516107648482602086016106ff565b91505092915050565b5f60208284031215610782576107816106e9565b5b61078c60206105dc565b90505f82015167ffffffffffffffff8111156107ab576107aa6106ed565b5b6107b784828501610740565b5f8301525092915050565b5f602082840312156107d7576107d661055e565b5b5f82015167ffffffffffffffff8111156107f4576107f3610562565b5b6108008482850161076d565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f61082d82610809565b6108378185610813565b93506108478185602086016106f1565b6108508161056e565b840191505092915050565b5f602083015f8301518482035f8601526108758282610823565b9150508091505092915050565b5f6020820190508181035f83015261089a818461085b565b905092915050565b5f819050919050565b6108b4816108a2565b81146108be575f80fd5b50565b5f815190506108cf816108ab565b92915050565b5f602082840312156108ea576108e961055e565b5b5f6108f7848285016108c1565b91505092915050565b610909816108a2565b82525050565b5f6020820190506109225f830184610900565b92915050565b5f602083015f8301518482035f8601526109428282610823565b9150508091505092915050565b5f6040820190508181035f8301526109678185610928565b9050818103602083015261097b818461085b565b90509392505050565b5f82825260208201905092915050565b5f61099e82610809565b6109a88185610984565b93506109b88185602086016106f1565b6109c18161056e565b840191505092915050565b5f6020820190508181035f8301526109e48184610994565b905092915050565b5f67ffffffffffffffff82169050919050565b610a08816109ec565b8114610a12575f80fd5b50565b5f81519050610a23816109ff565b92915050565b5f60208284031215610a3e57610a3d61055e565b5b5f610a4b84828501610a15565b91505092915050565b610a5d816109ec565b82525050565b5f602082019050610a765f830184610a54565b9291505056fea26469706673582212201305cd24dc5a8f09ab0f20f7149275842101d3e9bbb235941608cb65e3574c9864736f6c634300081a0033 \ No newline at end of file diff --git a/packages/evm/evmtest/wiki_how_tos/GetBalance.sol b/packages/evm/evmtest/wiki_how_tos/GetBalance.sol new file mode 100644 index 0000000000..35ae87d59b --- /dev/null +++ b/packages/evm/evmtest/wiki_how_tos/GetBalance.sol @@ -0,0 +1,39 @@ +// 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 getBalanceBaseTokens() public { + ISCAgentID memory agentID = ISC.sandbox.getSenderAccount(); + uint64 baseBalance = ISC.accounts.getL2BalanceBaseTokens(agentID); + emit GotBaseBalance(baseBalance); + } + + function getBalanceNativeTokens(bytes memory nativeTokenID) public { + ISCAgentID memory agentID = ISC.sandbox.getSenderAccount(); + NativeTokenID memory id = NativeTokenID({data: nativeTokenID}); + uint256 nativeTokens = ISC.accounts.getL2BalanceNativeTokens( + id, + agentID + ); + emit GotNativeTokenBalance(nativeTokens); + } + + function getBalanceNFTs() public { + ISCAgentID memory agentID = ISC.sandbox.getSenderAccount(); + uint256 nfts = ISC.accounts.getL2NFTAmount(agentID); + emit GotNFTIDs(nfts); + } + + function getAgentID() public { + ISCAgentID memory agentID = ISC.sandbox.getSenderAccount(); + emit GotAgentID(agentID.data); + } +} diff --git a/packages/evm/evmtest/wiki_how_tos/how_tos_test.go b/packages/evm/evmtest/wiki_how_tos/how_tos_test.go new file mode 100644 index 0000000000..2d0186b217 --- /dev/null +++ b/packages/evm/evmtest/wiki_how_tos/how_tos_test.go @@ -0,0 +1,114 @@ +package wiki_how_tos_test + +import ( + _ "embed" + "math/big" + "strings" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/iotaledger/wasp/packages/isc" + "github.com/iotaledger/wasp/packages/solo" + "github.com/iotaledger/wasp/packages/util" + "github.com/iotaledger/wasp/packages/vm/core/evm/evmtest" +) + +//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)) +) + +func TestBaseBalance(t *testing.T) { + env := evmtest.InitEVMWithSolo(t, solo.New(t), true) + privateKey, deployer := env.Chain.NewEthereumAccountWithL2Funds() + + instance := env.DeployContract(privateKey, GetBalanceContractABI, GetBalanceContractBytecode) + + balance, _ := env.Chain.EVM().Balance(deployer, nil) + decimals := env.Chain.EVM().BaseToken().Decimals + var value uint64 + instance.CallFnExpectEvent(nil, "GotBaseBalance", &value, "getBalanceBaseTokens") + realBalance := util.BaseTokensDecimalsToEthereumDecimals(value, decimals) + assert.Equal(t, balance, realBalance) +} + +func TestNativeBalance(t *testing.T) { + env := evmtest.InitEVMWithSolo(t, solo.New(t), true) + privateKey, deployer := env.Chain.NewEthereumAccountWithL2Funds() + + instance := env.DeployContract(privateKey, GetBalanceContractABI, 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) + + // 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) + + nativeBalance := new(big.Int) + instance.CallFnExpectEvent(nil, "GotNativeTokenBalance", &nativeBalance, "getBalanceNativeTokens", nativeTokenIDBytes) + assert.Equal(t, int64(100000), nativeBalance.Int64()) +} + +func TestNFTBalance(t *testing.T) { + env := evmtest.InitEVMWithSolo(t, solo.New(t), true) + privateKey, deployer := env.Chain.NewEthereumAccountWithL2Funds() + + instance := env.DeployContract(privateKey, GetBalanceContractABI, GetBalanceContractBytecode) + + // get the agentId of the contract deployer + senderAgentID := isc.NewEthereumAddressAgentID(env.Chain.ChainID, deployer) + + // 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.CallFnExpectEvent(nil, "GotNFTIDs", &nftBalance, "getBalanceNFTs") + assert.Equal(t, int64(1), nftBalance.Int64()) +} + +func TestAgentID(t *testing.T) { + env := evmtest.InitEVMWithSolo(t, solo.New(t), true) + privateKey, deployer := env.Chain.NewEthereumAccountWithL2Funds() + + instance := env.DeployContract(privateKey, GetBalanceContractABI, GetBalanceContractBytecode) + + // get the agentId of the contract deployer + senderAgentID := isc.NewEthereumAddressAgentID(env.Chain.ChainID, deployer) + + // get the agnetId of the contract deployer + // and compare it with the agentId returned by the contract + var agentID []byte + instance.CallFnExpectEvent(nil, "GotAgentID", &agentID, "getAgentID") + assert.Equal(t, senderAgentID.Bytes(), agentID) +}