Skip to content

Commit

Permalink
fix: contract periphery tests (#688)
Browse files Browse the repository at this point in the history
* fix: explicitly sort the tokens by addr

* fix: use vm.computeCreateAddress

* fix: mirror test sender params

* fix: use actual owner

* fix: add back gnosis

* Remove all reference to INFURA_ID (#687)

---------

Co-authored-by: John Feras <[email protected]>
  • Loading branch information
marcomariscal and jferas authored Jul 9, 2024
1 parent 5d63f2a commit dcd0ab2
Show file tree
Hide file tree
Showing 13 changed files with 59 additions and 39 deletions.
1 change: 0 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ env:
GNOSIS_CHAIN_RPC_URL: ${{ secrets.GNOSIS_CHAIN_RPC_URL }}
BASE_RPC_URL: $${{ secrets.BASE_RPC_URL }}
FOUNDRY_PROFILE: ci
INFURA_ID: ${{ secrets.INFURA_ID }}
WALLET_CONNECT_PROJECT_ID: ${{ secrets.WALLET_CONNECT_PROJECT_ID }}

jobs:
Expand Down
1 change: 0 additions & 1 deletion contracts-core/.env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
INFURA_ID=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
MNEMONIC=here is where your twelve words mnemonic should be put my friend
DEPLOY_GSN=false
ETHERSCAN_VERIFICATION_API_KEY="YOUR_API_KEY"
Expand Down
2 changes: 1 addition & 1 deletion contracts-periphery/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ install :; $(INSTALL_CMD)
test :; forge test --sender 0x4f78F7f3482D9f1790649f9DD18Eec5A1Cc70F86 --no-match-contract ApproveBatchSendTokensTest
test-gas :; forge test --match-path *.gas.t.sol
snapshot-gas :; forge test --match-path *.gas.t.sol --gas-report > snapshot/.gas
coverage :; forge coverage --report lcov --report summary && sed -i'.bak' 's/SF:/SF:contracts-periphery\//gI' lcov.info
coverage :; forge coverage --sender 0x4f78F7f3482D9f1790649f9DD18Eec5A1Cc70F86 --report lcov --report summary && sed -i'.bak' 's/SF:/SF:contracts-periphery\//gI' lcov.info
3 changes: 2 additions & 1 deletion contracts-periphery/script/ApproveBatchSendTokens.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import {UmbraBatchSend} from "src/UmbraBatchSend.sol";

contract ApproveBatchSendTokens is Script {
function run(
address _owner,
address _umbraContractAddress,
address _batchSendContractAddress,
address[] calldata _tokenAddressesToApprove
) public {
vm.startBroadcast();
vm.startBroadcast(_owner);
for (uint256 _i = 0; _i < _tokenAddressesToApprove.length; _i++) {
uint256 _currentAllowance = IERC20(_tokenAddressesToApprove[_i]).allowance(
_batchSendContractAddress, _umbraContractAddress
Expand Down
2 changes: 1 addition & 1 deletion contracts-periphery/script/DeployBatchSend.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ contract DeployBatchSend is Script {
/// @notice Deploy the contract to the list of networks,
function run() public {
// Compute the address the contract will be deployed to
address expectedContractAddress = computeCreateAddress(msg.sender, EXPECTED_NONCE);
address expectedContractAddress = vm.computeCreateAddress(msg.sender, EXPECTED_NONCE);
console2.log("Expected contract address: %s", expectedContractAddress);

// Turn off fallback to default RPC URLs since they can be flaky.
Expand Down
8 changes: 6 additions & 2 deletions contracts-periphery/test/ApproveBatchSendTokens.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ contract ApproveBatchSendTokensTest is Test {
address constant WBTC_ADDRESS = 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599;
address[] tokensToApprove =
[DAI_ADDRESS, LUSD_ADDRESS, RAI_ADDRESS, USDC_ADDRESS, USDT_ADDRESS, WBTC_ADDRESS];
address owner = 0xB7EE870E2c49B2DEEe70003519cF056247Aac3D4;

function setUp() public {
vm.createSelectFork(vm.rpcUrl("mainnet"), 18_428_858);
Expand All @@ -27,7 +28,10 @@ contract ApproveBatchSendTokensTest is Test {
address[] memory tokenAddressesToApprove = new address[](1);
tokenAddressesToApprove[0] = DAI_ADDRESS;
approveTokensScript.run(
umbraContractAddressOnMainnet, batchSendContractAddressOnMainnet, tokenAddressesToApprove
owner,
umbraContractAddressOnMainnet,
batchSendContractAddressOnMainnet,
tokenAddressesToApprove
);

assertEq(
Expand All @@ -40,7 +44,7 @@ contract ApproveBatchSendTokensTest is Test {

function test_ApproveMultipleTokens() public {
approveTokensScript.run(
umbraContractAddressOnMainnet, batchSendContractAddressOnMainnet, tokensToApprove
owner, umbraContractAddressOnMainnet, batchSendContractAddressOnMainnet, tokensToApprove
);

for (uint256 _i; _i < tokensToApprove.length; _i++) {
Expand Down
2 changes: 1 addition & 1 deletion contracts-periphery/test/DeployBatchSend.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ contract DeployBatchSendTest is DeployBatchSend, Test {
bytes batchSendCode;

function setUp() public {
expectedContractAddress = computeCreateAddress(sender, EXPECTED_NONCE);
expectedContractAddress = vm.computeCreateAddress(sender, EXPECTED_NONCE);
umbraBatchSendTest = new UmbraBatchSend(IUmbra(UMBRA));
batchSendCode = address(umbraBatchSendTest).code;
}
Expand Down
14 changes: 14 additions & 0 deletions contracts-periphery/test/UmbraBatchSend.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ abstract contract UmbraBatchSendTest is DeployUmbraTest {
error NotSorted();
error TooMuchEthSent();

function _sortSendDataByToken(UmbraBatchSend.SendData[] storage arr) internal {
for (uint256 i = 0; i < arr.length - 1; i++) {
for (uint256 j = 0; j < arr.length - i - 1; j++) {
if (arr[j].tokenAddr > arr[j + 1].tokenAddr) {
UmbraBatchSend.SendData memory temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}

function setUp() public virtual override {
super.setUp();
router = new UmbraBatchSend(IUmbra(address(umbra)));
Expand Down Expand Up @@ -94,6 +106,8 @@ abstract contract UmbraBatchSendTest is DeployUmbraTest {
sendData.push(UmbraBatchSend.SendData(alice, address(token), amount, pkx, ciphertext));
sendData.push(UmbraBatchSend.SendData(bob, address(token), amount2, pkx, ciphertext));

_sortSendDataByToken(sendData);

uint256 totalToll = toll * sendData.length;
token.approve(address(router), totalAmount);
token2.approve(address(router), totalAmount2);
Expand Down
1 change: 0 additions & 1 deletion frontend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ OPTIMISTIC_ETHERSCAN_API_KEY=yourOptimisticEtherscanApiKey
POLYGONSCAN_API_KEY=yourPolygonscanApiKey
ARBISCAN_API_KEY=yourArbiscanApiKey

INFURA_ID=yourKeyHere
BLOCKNATIVE_API_KEY=yourKeyHere
FORTMATIC_API_KEY=yourKeyHere
PORTIS_API_KEY=yourKeyHere
Expand Down
1 change: 0 additions & 1 deletion umbra-js/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ OPTIMISTIC_ETHERSCAN_API_KEY=yourOptimisticEtherscanApiKey
POLYGONSCAN_API_KEY=yourPolygonscanApiKey
ARBISCAN_API_KEY=yourArbiscanApiKey
GNOSISSCAN_API_KEY=yourGnosisSafeScanApiKey
INFURA_ID=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
MAINNET_RPC_URL=yourMainnetRpcUrl
OPTIMISM_RPC_URL=yourOptimismRpcUrl
GNOSIS_CHAIN_RPC_URL=yourGnosisChainRpcUrl
Expand Down
11 changes: 6 additions & 5 deletions umbra-js/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@ const chainIds = {
// Ensure that we have all the environment variables we need.
const mnemonic = 'test test test test test test test test test test test junk';

const infuraApiKey = process.env.INFURA_ID;
if (!infuraApiKey) throw new Error('Please set your INFURA_ID in a .env file');

function createTestnetConfig(network: keyof typeof chainIds): NetworkUserConfig {
const url = `https://${network}.infura.io/v3/${infuraApiKey as string}`;
const rpcUrlString = `${network.toUpperCase()}_RPC_URL`;
const url = process.env[rpcUrlString];
if (!url) throw new Error(`Please set the ${url} in a .env file`);
return {
accounts: {
count: 10,
Expand All @@ -36,12 +35,14 @@ function createTestnetConfig(network: keyof typeof chainIds): NetworkUserConfig
};
}

const rpcUrlString = process.env.SEPOLIA_RPC_URL;
if (!rpcUrlString) throw new Error('Please set the SEPOLIA_RPC_URL in a .env file');
const config: HardhatUserConfig = {
defaultNetwork: 'hardhat',
networks: {
hardhat: {
forking: {
url: `https://sepolia.infura.io/v3/${infuraApiKey}`,
url: rpcUrlString,
},
chainId: chainIds.hardhat,
accounts: {
Expand Down
8 changes: 3 additions & 5 deletions umbra-js/test/cns.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ const resolution = new Resolution({
uns: {
locations: {
Layer1: {
url: `https://mainnet.infura.io/v3/${String(process.env.INFURA_ID)}`,
url: `${String(process.env.MAINNET_RPC_URL)}`,
network: 'mainnet',
},
Layer2: {
url: `https://polygon-mainnet.infura.io/v3/${String(process.env.INFURA_ID)}`,
url: `${String(process.env.POLYGON_RPC_URL)}`,
network: 'polygon-mainnet',
},
},
Expand Down Expand Up @@ -43,9 +43,7 @@ describe('СNS functions', () => {

it('gets the public keys associated with a CNS address', async () => {
const address = await resolution.addr(name, 'ETH');
const ethersProvider = new StaticJsonRpcProvider(
`https://polygon-mainnet.infura.io/v3/${String(process.env.INFURA_ID)}`
);
const ethersProvider = new StaticJsonRpcProvider(`${String(process.env.POLYGON_RPC_URL)}`);
const keys = await utils.lookupRecipient(address, ethersProvider);
expect(keys.spendingPublicKey).to.equal(nameSpendingPublicKey);
expect(keys.viewingPublicKey).to.equal(nameViewingPublicKey);
Expand Down
44 changes: 25 additions & 19 deletions umbra-js/test/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,20 @@ import { Event } from '../src/ethers';

const ethersProvider = ethers.provider;

const INFURA_ID = <string>process.env.INFURA_ID;
if (!INFURA_ID) throw new Error('Please set your INFURA_ID in a .env file');
const MAINNET_RPC_URL = <string>process.env.MAINNET_RPC_URL;
if (!MAINNET_RPC_URL) throw new Error('Please set your MAINNET_RPC_URL in a .env file');

const SEPOLIA_RPC_URL = <string>process.env.SEPOLIA_RPC_URL;
if (!SEPOLIA_RPC_URL) throw new Error('Please set your SEPOLIA_RPC_URL in a .env file');

const POLYGON_RPC_URL = <string>process.env.POLYGON_RPC_URL;
if (!POLYGON_RPC_URL) throw new Error('Please set your POLYGON_RPC_URL in a .env file');

const OPTIMISM_RPC_URL = <string>process.env.OPTIMISM_RPC_URL;
if (!OPTIMISM_RPC_URL) throw new Error('Please set your OPTIMISM_RPC_URL in a .env file');

const ARBITRUM_ONE_RPC_URL = <string>process.env.ARBITRUM_ONE_RPC_URL;
if (!ARBITRUM_ONE_RPC_URL) throw new Error('Please set your ARBITRUM_ONE_RPC_URL in a .env file');

// Public key and address corresponding to stratus4.eth
const publicKey = '0x04458465db23fe07d148c8c9078d8b67497998a66f4f2aa479973a9cbaaf8b5a96e6ba166a389b8f794b68010849b64b91343e72c7fa4cfcc178607c4b1d4870ed'; // prettier-ignore
Expand Down Expand Up @@ -109,29 +121,29 @@ describe('Utilities', () => {

// --- Address, advanced mode on (i.e. don't use the StealthKeyRegistry) ---
it('looks up recipients by address, advanced mode on', async () => {
const ethersProvider = new StaticJsonRpcProvider(`https://sepolia.infura.io/v3/${String(process.env.INFURA_ID)}`);
const ethersProvider = new StaticJsonRpcProvider(SEPOLIA_RPC_URL);
const keys = await utils.lookupRecipient(address, ethersProvider, { advanced: true });
expect(keys.spendingPublicKey).to.equal(pubKeysWallet.spendingPublicKey);
expect(keys.viewingPublicKey).to.equal(pubKeysWallet.viewingPublicKey);
});

it('looks up recipients by ENS, advanced mode on', async () => {
const ethersProvider = new StaticJsonRpcProvider(`https://sepolia.infura.io/v3/${String(process.env.INFURA_ID)}`);
const ethersProvider = new StaticJsonRpcProvider(SEPOLIA_RPC_URL);
const keys = await utils.lookupRecipient('stratus4.eth', ethersProvider, { advanced: true });
expect(keys.spendingPublicKey).to.equal(pubKeysWallet.spendingPublicKey);
expect(keys.viewingPublicKey).to.equal(pubKeysWallet.viewingPublicKey);
});

it.skip('looks up recipients by CNS, advanced mode on', async () => {
const ethersProvider = new StaticJsonRpcProvider(`https://sepolia.infura.io/v3/${INFURA_ID}`);
const ethersProvider = new StaticJsonRpcProvider(SEPOLIA_RPC_URL);
const keys = await utils.lookupRecipient('udtestdev-msolomon.crypto', ethersProvider, { advanced: true });
expect(keys.spendingPublicKey).to.equal(pubKeysWallet.spendingPublicKey);
expect(keys.viewingPublicKey).to.equal(pubKeysWallet.viewingPublicKey);
});

// --- Address, advanced mode off (i.e. use the StealthKeyRegistry) ---
it('looks up recipients by address, advanced mode off', async () => {
const ethersProvider = new StaticJsonRpcProvider(`https://sepolia.infura.io/v3/${INFURA_ID}`); // otherwise throws with unsupported network since we're on localhost
const ethersProvider = new StaticJsonRpcProvider(SEPOLIA_RPC_URL); // otherwise throws with unsupported network since we're on localhost
const keys = await utils.lookupRecipient(address, ethersProvider);
expect(keys.spendingPublicKey).to.equal(pubKeysUmbra.spendingPublicKey);
expect(keys.viewingPublicKey).to.equal(pubKeysUmbra.viewingPublicKey);
Expand All @@ -143,7 +155,7 @@ describe('Utilities', () => {
});

it('looks up recipients by ENS, advanced mode off', async () => {
const ethersProvider = new StaticJsonRpcProvider(`https://sepolia.infura.io/v3/${INFURA_ID}`);
const ethersProvider = new StaticJsonRpcProvider(SEPOLIA_RPC_URL);
const keys = await utils.lookupRecipient('stratus4.eth', ethersProvider);
// These values are set on the Sepolia resolver
expect(keys.spendingPublicKey).to.equal(pubKeysUmbra.spendingPublicKey);
Expand Down Expand Up @@ -181,37 +193,31 @@ describe('Utilities', () => {

// --- Address history by network ---
it('looks up transaction history on mainnet', async () => {
const ethersProvider = new StaticJsonRpcProvider(`https://mainnet.infura.io/v3/${INFURA_ID}`);
const ethersProvider = new StaticJsonRpcProvider(MAINNET_RPC_URL);
const txHash = await utils.getSentTransaction(address, ethersProvider);
expect(txHash).to.have.lengthOf(66);
});

it('looks up transaction history on sepolia', async () => {
const ethersProvider = new StaticJsonRpcProvider(`https://sepolia.infura.io/v3/${INFURA_ID}`);
const ethersProvider = new StaticJsonRpcProvider(SEPOLIA_RPC_URL);
const txHash = await utils.getSentTransaction(address, ethersProvider);
expect(txHash).to.have.lengthOf(66);
});

it('looks up transaction history on polygon', async () => {
const ethersProvider = new ethers.providers.StaticJsonRpcProvider(
`https://polygon-mainnet.infura.io/v3/${INFURA_ID}`
) as EthersProvider;
const ethersProvider = new ethers.providers.StaticJsonRpcProvider(POLYGON_RPC_URL) as EthersProvider;
const txHash = await utils.getSentTransaction(address, ethersProvider);
expect(txHash).to.have.lengthOf(66);
});

it('looks up transaction history on optimism', async () => {
const ethersProvider = new ethers.providers.StaticJsonRpcProvider(
`https://optimism-mainnet.infura.io/v3/${INFURA_ID}`
) as EthersProvider;
const ethersProvider = new ethers.providers.StaticJsonRpcProvider(OPTIMISM_RPC_URL) as EthersProvider;
const txHash = await utils.getSentTransaction(address, ethersProvider);
expect(txHash).to.have.lengthOf(66);
});

it('looks up transaction history on arbitrum one', async () => {
const ethersProvider = new ethers.providers.StaticJsonRpcProvider(
`https://arbitrum-mainnet.infura.io/v3/${INFURA_ID}`
) as EthersProvider;
const ethersProvider = new ethers.providers.StaticJsonRpcProvider(ARBITRUM_ONE_RPC_URL) as EthersProvider;
const txHash = await utils.getSentTransaction(address, ethersProvider);
expect(txHash).to.have.lengthOf(66);
});
Expand All @@ -238,7 +244,7 @@ describe('Utilities', () => {

it('throws when looking up an address that has not sent a transaction', async () => {
const address = '0x0000000000000000000000000000000000000002';
const ethersProvider = new StaticJsonRpcProvider(`https://sepolia.infura.io/v3/${INFURA_ID}`); // otherwise throws with unsupported network since we're on localhost
const ethersProvider = new StaticJsonRpcProvider(SEPOLIA_RPC_URL); // otherwise throws with unsupported network since we're on localhost
const errorMsg = `Address ${address} has not registered stealth keys. Please ask them to setup their Umbra account`;
await expectRejection(utils.lookupRecipient(address, ethersProvider), errorMsg);
});
Expand Down

0 comments on commit dcd0ab2

Please sign in to comment.