Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add integration tests for Anvil migrations #11002

Merged
merged 41 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
cd987f3
test(protocol/migrations_sol): adds existing unit tests
arthurgousset May 21, 2024
601ad7c
Merge branch 'master' into arthurgousset/chore/anvil-integration-tests
arthurgousset May 24, 2024
3ae51c4
Merge branch 'master' into arthurgousset/chore/anvil-integration-tests
arthurgousset May 28, 2024
ee24877
test(test-sol/integration): adds e2e test for GoldToken
arthurgousset May 28, 2024
714bc75
test(test-sol/integration): adds loop to assert contract is in Registry
arthurgousset May 29, 2024
8651f31
chore(test-sol/integration): adds TODO comment about config file
arthurgousset May 29, 2024
eec3863
test(test-sol/integration): upgrades to solidity 0.8
arthurgousset May 30, 2024
710059f
Merge branch 'master' into arthurgousset/chore/anvil-integration-tests
arthurgousset May 30, 2024
c4f55d5
nit(test-sol/integration): updates constructor visibility
arthurgousset May 30, 2024
de6b143
nit(test-sol/integration): updates function state mutability
arthurgousset May 30, 2024
d99a746
test(test-sol/integration): adds MVP assertion that bytecode matches
arthurgousset May 30, 2024
4df1e7c
fix(test-sol/integration): use implementation address and deployedByt…
arthurgousset May 30, 2024
dc6a6c5
refactor(test-sol): adds registry array in `constants.sol`
arthurgousset May 31, 2024
d6389c8
refactor(protocol/migration_sol): uses registry array from `constants…
arthurgousset May 31, 2024
ab7bab9
fix(test-sol/integration): adds back `Test.sol` import
arthurgousset May 31, 2024
e372b8a
refactor(migrations_sol): simplifies script that runs integration tests
arthurgousset May 31, 2024
130523e
chore(test-sol/integration): commits WIP on failing bytecode test
arthurgousset May 31, 2024
1e61942
test(test-sol): adds helper to remove metadata from bytecode
arthurgousset May 31, 2024
e55c973
chore(test-sol/integration): excludes failing contracts from bytecode…
arthurgousset May 31, 2024
14bd4cf
chor(test-sol/integration): adds code comment for readability
arthurgousset May 31, 2024
075697e
chore(test-sol/integration): removing unused code comments
arthurgousset May 31, 2024
41bff1b
fix(workflows/protocol_tests): excludes integration tests
arthurgousset May 31, 2024
c7511a8
fix(workflows/protocol_tests): excludes integration tests more explic…
arthurgousset Jun 3, 2024
e983e9a
Merge branch 'master' into arthurgousset/chore/anvil-integration-tests
arthurgousset Jun 3, 2024
bb386de
nit(test-sol/constants): improves code comment for context
arthurgousset Jun 3, 2024
a4d4d8b
Merge branch 'arthurgousset/chore/anvil-integration-tests' of github.…
arthurgousset Jun 3, 2024
1f7ab42
fix(workflows/protocol_tests): downgrades foundry version
arthurgousset Jun 3, 2024
2f9f837
fix(workflows/protocol_tests): excludes integration tests correctly
arthurgousset Jun 4, 2024
30de987
chore(test-sol/utils): reverts `deployCodeTo` edit in `ECDSAHelper`
arthurgousset Jun 4, 2024
dcb09e1
style(protocol): linting
arthurgousset Jun 4, 2024
c27a53e
docs(workflows/protocol_tests): adds better code comment
arthurgousset Jun 4, 2024
b9ce129
refactor(test-sol/integration): rename variables for better readability
arthurgousset Jun 4, 2024
7a740cb
refactor(test-sol/integration): take constants out of `for`-loop
arthurgousset Jun 4, 2024
7201463
style(protocol): linting
arthurgousset Jun 4, 2024
19faa9b
fix(test-sol/integration): add contract name back into `for`-loop
arthurgousset Jun 4, 2024
d31c336
nit(test-sol/integration): rename variable for better readability
arthurgousset Jun 4, 2024
a7f4905
refactor(migrations_sol/constants): creates new `constants.sol`
arthurgousset Jun 4, 2024
75a4306
refactor(migrations_sol&test-sol): removes `Utils` import
arthurgousset Jun 4, 2024
1e6b230
test(test-sol/integration): bumps solidity version to `>=0.8.7 <0.8.20`
arthurgousset Jun 4, 2024
9c913ca
refactor(test-sol/integration): use `.code` property instead of helpe…
arthurgousset Jun 5, 2024
255f467
refactor(foundry): simplifies configs to exclude tests
arthurgousset Jun 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
64 changes: 63 additions & 1 deletion packages/protocol/migrations_sol/integration_tests.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,66 @@
#!/usr/bin/env bash
set -euo pipefail

forge test --fork-url http://127.0.0.1:$ANVIL_PORT --match-contract=IntegrationTest -vvv # || echo "Test failed" # TODO for some reason the echo didn't work
: '
The following runs specific integration tests.
'
# Run integration tests
forge test \
--match-contract=IntegrationTest \
-vvv \
--fork-url http://127.0.0.1:$ANVIL_PORT

: '
The following tests assert that existing unit tests pass when run against the migrated anvil fork.
These are necessary, but not sufficient requirements.
arthurgousset marked this conversation as resolved.
Show resolved Hide resolved
The idea is that existing unit tests, which are known to pass in a testing environment, should
also pass if they are run against the devchain using the "--fork-url" flag.
'
# Run tests common
# can't use gas limit because some setUp function use more than the limit
forge test \
--match-path "test-sol/common/*" \
-vvv \
--fork-url http://127.0.0.1:$ANVIL_PORT

arthurgousset marked this conversation as resolved.
Show resolved Hide resolved
# Run tests governance/network
forge test \
--match-path "test-sol/governance/network/*" \
--block-gas-limit 50000000 \
-vvv \
--fork-url http://127.0.0.1:$ANVIL_PORT

# Run tests governance/validators
forge test \
--match-path "test-sol/governance/validators/*" \
--block-gas-limit 50000000 \
-vvv \
--fork-url http://127.0.0.1:$ANVIL_PORT

# Run tests governance/voting
# can't use gas limit because some setUp function use more than the limit
forge test \
--match-path "test-sol/governance/voting/*" \
--block-gas-limit 50000000 \
-vvv \
--fork-url http://127.0.0.1:$ANVIL_PORT

# Run tests stability
forge test \
--match-path "test-sol/stability/*" \
--block-gas-limit 50000000 \
-vvv \
--fork-url http://127.0.0.1:$ANVIL_PORT

# Run tests identity
forge test \
--match-path "test-sol/identity/*" \
--block-gas-limit 50000000 \
-vvv \
--fork-url http://127.0.0.1:$ANVIL_PORT

# Run Everything just in case something was missed
# can't use gas limit because some setUp function use more than the limit
forge test \
-vvv \
--fork-url http://127.0.0.1:$ANVIL_PORT #TODO this should ignore integration tests
87 changes: 79 additions & 8 deletions packages/protocol/test-sol/integration/Integration.t.sol
Original file line number Diff line number Diff line change
@@ -1,19 +1,90 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.5.13;
pragma solidity >=0.5.13 <0.8.20;
arthurgousset marked this conversation as resolved.
Show resolved Hide resolved

// import "forge-std/console2.sol";

// import { Constants } from "@test-sol/constants.sol";
import "celo-foundry/Test.sol";
import "@celo-contracts/common/GoldToken.sol";
// import "@celo-contracts/common/test/MockGoldToken.sol";
import "forge-std/console.sol";
import { Utils } from "@test-sol/utils.sol";
import "@celo-contracts/common/interfaces/IRegistry.sol";
import "@celo-contracts/common/interfaces/IProxy.sol";


contract IntegrationTest is Test {
address constant registryAddress = address(0x000000000000000000000000000000000000ce10);
address account1 = actor("account1");
address account2 = actor("account2");
IRegistry registry = IRegistry(registryAddress);

function setUp() public {}
// address account1 = actor("account1");
// address account2 = actor("account2");

function test_dummy() public {}
function setUp() public {}
}

contract RegistryIntegrationTest is IntegrationTest, Utils {
string[23] expectedContractsInRegistry;
IProxy proxy;

// TODO(Arthur): Consider moving this to a config file. Perhaps make the migration depend
// on that file too?
constructor() public {
expectedContractsInRegistry = [
"Accounts",
"BlockchainParameters",
"DoubleSigningSlasher",
"DowntimeSlasher",
"Election",
"EpochRewards",
"Escrow",
"FederatedAttestations",
"FeeCurrencyWhitelist",
"FeeCurrencyDirectory",
"Freezer",
"FeeHandler",
"GoldToken",
"Governance",
"GovernanceSlasher",
"LockedGold",
"OdisPayments",
"Random",
"Registry",
"SortedOracles",
"UniswapFeeHandlerSeller",
"MentoFeeHandlerSeller",
"Validators"
];
}

function test_shouldHaveAddressInRegistry() public view {
for (uint256 i = 0; i < expectedContractsInRegistry.length; i++) {
string memory contractName = expectedContractsInRegistry[i];
address contractAddress = registry.getAddressFor(keccak256(abi.encodePacked(contractName)));
console2.log(contractName, "address in Registry is: ", contractAddress);
assert(contractAddress != address(0));
}
}

function test_shouldHaveCorrectBytecode() public {
////////////////////DEBUGGING: START/////////////////////////
// SPECIFIC EXAMPLE REGISTRY.SOL BEFORE LOOPING OVER ALL CONTRACTS
string memory contractName = "Registry";
address proxyAddress = registry.getAddressForStringOrDie(contractName);
proxy = IProxy(address(uint160(proxyAddress)));
////////////////////DEBUGGING: END///////////////////////////

address implementationAddress = proxy._getImplementation();
console2.log("Implementation address is :", implementationAddress);

// Get bytecode from deployed contract (in Solidity 0.5)
bytes memory actualBytecode = getCodeAt(implementationAddress); // IProxy.sol and Proxy.sol are 0.5
// Get bytecode from build artifacts
bytes memory expectedBytecode = vm.getDeployedCode("Registry.sol");

// // Get bytecode from deployed contract (in Solidity 0.8)
// bytes memory actualBytecode = implementationAddress.code;
// // Get bytecode from build artifacts (in Solidity 0.8)
// bytes memory expectedBytecode = vm.getDeployedCode(string.concat(contractName, ".sol"));

// Compare the bytecodes
assertEq(actualBytecode, expectedBytecode, "Bytecode does not match");
arthurgousset marked this conversation as resolved.
Show resolved Hide resolved
}
}
21 changes: 21 additions & 0 deletions packages/protocol/test-sol/utils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,25 @@ contract Utils is Test {
(uint256(keccak256(abi.encodePacked(block.timestamp, block.difficulty, msg.sender, salt))) %
(max - min + 1)) + min;
}

// Get the runtime code or "deployedBytecode" at a contract address.
// Using the `.code` or `.runtime` property on a contract is only available in Solidity 0.8.0 and later.
// On Solity <0.8.0, inline assembly is necessary to retrieve the bytecode of a contract.
// This implementation is taken from the Solidity documentation.
// Source: https://docs.soliditylang.org/en/v0.4.24/assembly.html#example
function getCodeAt(address _addr) public view returns (bytes memory o_code) {
assembly {
// retrieve the size of the code, this needs assembly
let size := extcodesize(_addr)
// allocate output byte array - this could also be done without assembly
// by using o_code = new bytes(size)
o_code := mload(0x40)
// new "memory end" including padding
mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
// store length in memory
mstore(o_code, size)
// actually retrieve the code, this needs assembly
extcodecopy(_addr, add(o_code, 0x20), 0, size)
}
}
}