From f4c0af5207363b622fe94751c922d163c172fb23 Mon Sep 17 00:00:00 2001 From: Gjermund Garaba Date: Thu, 1 Aug 2024 11:33:09 +0200 Subject: [PATCH] Deploy contracts in e2e test --- e2e/artifacts/genesis.json | 4 +- e2e/interchaintestv8/e2esuite/utils.go | 57 +++++++++++++++++---- e2e/interchaintestv8/e2esuite/utils_test.go | 55 ++++++++++++++++++++ e2e/interchaintestv8/ibc_eureka_test.go | 13 ++++- e2e/interchaintestv8/testvalues/values.go | 27 ++++++---- script/E2ETestDeploy.s.sol | 23 +++++++-- 6 files changed, 153 insertions(+), 26 deletions(-) create mode 100644 e2e/interchaintestv8/e2esuite/utils_test.go diff --git a/e2e/artifacts/genesis.json b/e2e/artifacts/genesis.json index 85f3a57..402a050 100644 --- a/e2e/artifacts/genesis.json +++ b/e2e/artifacts/genesis.json @@ -1,6 +1,6 @@ { - "trustedClientState": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000012754500000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000673696d642d310000000000000000000000000000000000000000000000000000", - "trustedConsensusState": "0000000000000000000000000000000000000000000000000000000066ab43b7e469beedd6bb30c2ebf99c96eb35b3c4c16a12d1864bc760bb5f5dcb818e31f07b4f934390c9446d17e0663a6e482c78a39cffa0899a13aa1cb6d60fac76c64f", + "trustedClientState": "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000012754500000000000000000000000000000000000000000000000000000000001baf800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000673696d642d310000000000000000000000000000000000000000000000000000", + "trustedConsensusState": "0000000000000000000000000000000000000000000000000000000066ab560477a0f511875a5c312746bd2a9f2bfbe32288ea114dd17a3655db747a52fccecd4cdf7b7ff66fac473c9160869386ab500eb2db76f1f421e645f8f1634d052389", "updateClientVkey": "0x008d1636cb723e4319abda291c18f7dd68e37c2703f6da3733c3a998bfa039f3", "membershipVkey": "0x0014aa880aba41e680e859af6ebdefef52df9902ab61975bd1bb340c9b820b2a", "ucAndMembershipVkey": "0x001d0fed4a58085ccac826775bfe0553ae6e42e52521aa52c3601396854dc4e8" diff --git a/e2e/interchaintestv8/e2esuite/utils.go b/e2e/interchaintestv8/e2esuite/utils.go index d436a86..7e891cf 100644 --- a/e2e/interchaintestv8/e2esuite/utils.go +++ b/e2e/interchaintestv8/e2esuite/utils.go @@ -2,8 +2,9 @@ package e2esuite import ( "context" - "fmt" + "encoding/json" "regexp" + "strings" "cosmossdk.io/math" @@ -16,6 +17,23 @@ import ( "github.com/strangelove-ventures/interchaintest/v8/testutil" ) +type ForgeScriptReturnValues struct { + InternalType string `json:"internal_type"` + Value string `json:"value"` +} + +type ForgeDeployOutput struct { + Returns map[string]ForgeScriptReturnValues `json:"returns"` +} + +type DeployedContracts struct { + Ics07Tendermint string `json:"ics07Tendermint"` + Ics02Client string `json:"ics02Client"` + Ics26Router string `json:"ics26Router"` + Ics20Transfer string `json:"ics20Transfer"` + Erc20 string `json:"erc20"` +} + // FundAddressChainB sends funds to the given address on Chain B. // The amount sent is 1,000,000,000 of the chain's denom. func (s *TestSuite) FundAddressChainB(ctx context.Context, address string) { @@ -69,15 +87,32 @@ func (s *TestSuite) fundAddress(ctx context.Context, chain *cosmos.CosmosChain, s.Require().NoError(err) } -func (s *TestSuite) GetEthAddressFromStdout(stdout string) string { - // Define the regular expression pattern - re := regexp.MustCompile(`"value":"(0x[0-9a-fA-F]+)"`) +func (s *TestSuite) GetEthContractsFromDeployOutput(stdout string) DeployedContracts { + // Extract the JSON part using regex + re := regexp.MustCompile(`\{.*\}`) + jsonPart := re.FindString(stdout) - // Find the first match - matches := re.FindStringSubmatch(stdout) - if len(matches) <= 1 { - s.FailNow(fmt.Sprintf("no match found in stdout: %s", stdout)) - } - // Extract the value - return matches[1] + var returns ForgeDeployOutput + err := json.Unmarshal([]byte(jsonPart), &returns) + s.Require().NoError(err) + + // Extract the embedded JSON string + s.Require().Len(returns.Returns, 1) + embeddedJsonStr := returns.Returns["0"].Value + + // Unescape and remove surrounding quotes + embeddedJsonStr = strings.ReplaceAll(embeddedJsonStr, `\"`, `"`) + embeddedJsonStr = strings.Trim(embeddedJsonStr, `"`) + + var embeddedContracts DeployedContracts + err = json.Unmarshal([]byte(embeddedJsonStr), &embeddedContracts) + s.Require().NoError(err) + + s.Require().NotEmpty(embeddedContracts.Erc20) + s.Require().NotEmpty(embeddedContracts.Ics02Client) + s.Require().NotEmpty(embeddedContracts.Ics07Tendermint) + s.Require().NotEmpty(embeddedContracts.Ics20Transfer) + s.Require().NotEmpty(embeddedContracts.Ics26Router) + + return embeddedContracts } diff --git a/e2e/interchaintestv8/e2esuite/utils_test.go b/e2e/interchaintestv8/e2esuite/utils_test.go new file mode 100644 index 0000000..98e42f8 --- /dev/null +++ b/e2e/interchaintestv8/e2esuite/utils_test.go @@ -0,0 +1,55 @@ +package e2esuite + +import ( + "testing" + + "testing" + + "github.com/stretchr/testify/require" +) + +func TestGetEthAddressFromStdout(t *testing.T) { + exampleOutput := `Compiling 1 files with Solc 0.8.25 +Solc 0.8.25 finished in 2.74s +Compiler run successful! +EIP-3855 is not supported in one or more of the RPCs used. +Unsupported Chain IDs: 31337. +Contracts deployed with a Solidity version equal or higher than 0.8.20 might not work properly. +For more information, please see https://eips.ethereum.org/EIPS/eip-3855 +{"logs":[],"gas_used":11048147,"returns":{"0":{"internal_type":"string","value":"\"{\\\"erc20\\\":\\\"0x51f71E738F3D4577a7d9232DAFdE6e4cAB140947\\\",\\\"ics02Client\\\":\\\"0x564dA7794e99994137470505c2A8F6Bd17002D0f\\\",\\\"ics07Tendermint\\\":\\\"0xBC05F607DDde69B2Dc571a1d565d79466a2FDD8A\\\",\\\"ics20Transfer\\\":\\\"0xb2911d67B35b582b10828465E0c76aEDbb907d75\\\",\\\"ics26Router\\\":\\\"0xbbABA12ba070C22C0c59FAdD8d8dFa3e16231aA6\\\"}\""}}} + +## Setting up 1 EVM. + +========================== + +Chain 31337 + +Estimated gas price: 0.018684681 gwei + +Estimated total gas used for script: 15503518 + +Estimated amount required: 0.000289678288207758 ETH + +========================== + + +========================== + +ONCHAIN EXECUTION COMPLETE & SUCCESSFUL. + +Transactions saved to: /home/foundry./broadcast/E2ETestDeploy.s.sol/31337/run-latest.json + +Sensitive values saved to: /home/foundry./cache/E2ETestDeploy.s.sol/31337/run-latest.json +` + + testSuite := &TestSuite{} + testSuite.SetT(t) + + deployedContracts := testSuite.GetEthContractsFromDeployOutput(exampleOutput) + + require.Equal(t, "0xBC05F607DDde69B2Dc571a1d565d79466a2FDD8A", deployedContracts.Ics07Tendermint) + require.Equal(t, "0x564dA7794e99994137470505c2A8F6Bd17002D0f", deployedContracts.Ics02Client) + require.Equal(t, "0xbbABA12ba070C22C0c59FAdD8d8dFa3e16231aA6", deployedContracts.Ics26Router) + require.Equal(t, "0xb2911d67B35b582b10828465E0c76aEDbb907d75", deployedContracts.Ics20Transfer) + require.Equal(t, "0x51f71E738F3D4577a7d9232DAFdE6e4cAB140947", deployedContracts.Erc20) +} diff --git a/e2e/interchaintestv8/ibc_eureka_test.go b/e2e/interchaintestv8/ibc_eureka_test.go index 43f80d6..dc2fa7d 100644 --- a/e2e/interchaintestv8/ibc_eureka_test.go +++ b/e2e/interchaintestv8/ibc_eureka_test.go @@ -95,7 +95,12 @@ func (s *IbcEurekaTestSuite) SetupSuite(ctx context.Context) { }) s.Require().NoError(err, fmt.Sprintf("error deploying contracts: \nstderr: %s\nstdout: %s", stderr, stdout)) - // os.Setenv(testvalues.EnvKeyContractAddress, contractAddress) + deployedContracts := s.GetEthContractsFromDeployOutput(string(stdout)) + os.Setenv(testvalues.EnvKeySP1ICS07TendermintContractAddress, deployedContracts.Ics07Tendermint) + os.Setenv(testvalues.EnvKeyICS02ClientContractAddress, deployedContracts.Ics02Client) + os.Setenv(testvalues.EnvKeyICS26RouterContractAddress, deployedContracts.Ics26Router) + os.Setenv(testvalues.EnvKeyICS20TransferContractAddress, deployedContracts.Ics20Transfer) + os.Setenv(testvalues.EnvKeyERC20ContractAddress, deployedContracts.Erc20) _, err = ethclient.Dial(eth.GetHostRPCAddress()) s.Require().NoError(err) @@ -116,5 +121,11 @@ func (s *IbcEurekaTestSuite) TestDeploy() { _, _ = s.ChainA, s.ChainB s.Require().True(s.Run("Verify deployment", func() { + // Verify that the contracts have been deployed + s.Require().NotEmpty(os.Getenv(testvalues.EnvKeySP1ICS07TendermintContractAddress)) + s.Require().NotEmpty(os.Getenv(testvalues.EnvKeyICS02ClientContractAddress)) + s.Require().NotEmpty(os.Getenv(testvalues.EnvKeyICS26RouterContractAddress)) + s.Require().NotEmpty(os.Getenv(testvalues.EnvKeyICS20TransferContractAddress)) + s.Require().NotEmpty(os.Getenv(testvalues.EnvKeyERC20ContractAddress)) })) } diff --git a/e2e/interchaintestv8/testvalues/values.go b/e2e/interchaintestv8/testvalues/values.go index 8bbd341..bbf5f8f 100644 --- a/e2e/interchaintestv8/testvalues/values.go +++ b/e2e/interchaintestv8/testvalues/values.go @@ -14,25 +14,34 @@ const ( // StartingTokenAmount is the amount of tokens to give to each user at the start of the test. StartingTokenAmount int64 = 10_000_000_000 - // Address of the SP1ICS07Tendermint contract. - EnvKeyContractAddress = "CONTRACT_ADDRESS" - // Tendermint RPC URL. + // EnvKeyTendermintRPC Tendermint RPC URL. EnvKeyTendermintRPC = "TENDERMINT_RPC_URL" - // Ethereum RPC URL. + // EnvKeyEthRPC Ethereum RPC URL. EnvKeyEthRPC = "RPC_URL" - // Private key used to submit transactions by the operator. + // EnvKeyPrivateKey Private key used to submit transactions by the operator. EnvKeyPrivateKey = "PRIVATE_KEY" - // The prover type (local|network|mock). + // EnvKeySp1Prover The prover type (local|network|mock). EnvKeySp1Prover = "SP1_PROVER" - // Private key for the prover network. + // EnvKeySp1PrivateKey Private key for the prover network. EnvKeySp1PrivateKey = "SP1_PRIVATE_KEY" + + // EnvKeySP1ICS07TendermintContractAddress Address of the SP1ICS07Tendermint contract. + EnvKeySP1ICS07TendermintContractAddress = "SP1_ICS07_TENDERMINT_CONTRACT_ADDRESS" + // EnvKeyICS02ClientContractAddress Address of the ICS02Client contract. + EnvKeyICS02ClientContractAddress = "ICS02_CLIENT_CONTRACT_ADDRESS" + // EnvKeyICS26RouterContractAddress Address of the ICS26Router contract. + EnvKeyICS26RouterContractAddress = "ICS26_ROUTER_CONTRACT_ADDRESS" + // EnvKeyICS20TransferContractAddress Address of the ICS20Transfer contract. + EnvKeyICS20TransferContractAddress = "ICS20_TRANSFER_CONTRACT_ADDRESS" + // EnvKeyERC20ContractAddress Address of the ERC20 contract. + EnvKeyERC20ContractAddress = "ERC20_CONTRACT_ADDRESS" ) var ( - // Maximum period to deposit on a proposal. + // MaxDepositPeriod Maximum period to deposit on a proposal. // This value overrides the default value in the gov module using the `modifyGovV1AppState` function. MaxDepositPeriod = time.Second * 10 - // Duration of the voting period. + // VotingPeriod Duration of the voting period. // This value overrides the default value in the gov module using the `modifyGovV1AppState` function. VotingPeriod = time.Second * 30 diff --git a/script/E2ETestDeploy.s.sol b/script/E2ETestDeploy.s.sol index 68f2c08..d91232e 100644 --- a/script/E2ETestDeploy.s.sol +++ b/script/E2ETestDeploy.s.sol @@ -6,6 +6,10 @@ import { Script } from "forge-std/Script.sol"; import { SP1ICS07Tendermint } from "@cosmos/sp1-ics07-tendermint/SP1ICS07Tendermint.sol"; import { SP1Verifier } from "@sp1-contracts/v1.0.1/SP1Verifier.sol"; import { IICS07TendermintMsgs } from "@cosmos/sp1-ics07-tendermint/msgs/IICS07TendermintMsgs.sol"; +import { ICS02Client } from "../src/ICS02Client.sol"; +import { ICS26Router } from "../src/ICS26Router.sol"; +import { ICS20Transfer } from "../src/ICS20Transfer.sol"; +import { TestERC20 } from "../test/TestERC20.sol"; struct SP1ICS07TendermintGenesisJson { bytes trustedClientState; @@ -19,7 +23,7 @@ struct SP1ICS07TendermintGenesisJson { contract E2ETestDeploy is Script { using stdJson for string; - function run() public returns (address, address, address, address, address) { + function run() public returns (string memory) { // Read the initialization parameters for the SP1 Tendermint contract. SP1ICS07TendermintGenesisJson memory genesis = loadGenesis("genesis.json"); IICS07TendermintMsgs.ConsensusState memory trustedConsensusState = @@ -28,7 +32,7 @@ contract E2ETestDeploy is Script { vm.startBroadcast(); - // TODO: Implement the deployment script here. + // Deploy the SP1 ICS07 Tendermint light client SP1Verifier verifier = new SP1Verifier(); SP1ICS07Tendermint ics07Tendermint = new SP1ICS07Tendermint( genesis.updateClientVkey, @@ -39,9 +43,22 @@ contract E2ETestDeploy is Script { trustedConsensusHash ); + // Deploy IBC Eureka + ICS02Client ics02Client = new ICS02Client(address(this)); + ICS26Router ics26Router = new ICS26Router(address(ics02Client), address(this)); + ICS20Transfer ics20Transfer = new ICS20Transfer(address(ics26Router)); + TestERC20 erc20 = new TestERC20(); + vm.stopBroadcast(); - return (address(ics07Tendermint), address(0), address(0), address(0), address(0)); + string memory json = "json"; + json.serialize("ics07Tendermint", address(ics07Tendermint)); + json.serialize("ics02Client", address(ics02Client)); + json.serialize("ics26Router", address(ics26Router)); + json.serialize("ics20Transfer", address(ics20Transfer)); + string memory finalJson = json.serialize("erc20", address(erc20)); + + return finalJson; } function loadGenesis(string memory fileName) public view returns (SP1ICS07TendermintGenesisJson memory) {