Skip to content

Commit

Permalink
chore: backport Interchain address tracker change (#113)
Browse files Browse the repository at this point in the history
* fix: minor test coverage gaps (#111)

* fix: minor test coverage gaps

* fix: revert message

---------

Co-authored-by: Dean Amiel <[email protected]>

* fix(InterchainAddressTracker): removing Upgradable (#112)

* fix(InterchainAddressTracker): removing Upgradable

* chore(npm): version bump

* chore(npm): version bump

* Update contracts/test/utils/TestInterchainAddressTracker.sol

* style(solidity): prettier

* fix(InterchainAddressTracker): removing unused function

---------

Co-authored-by: Milap Sheth <[email protected]>

---------

Co-authored-by: Dean <[email protected]>
Co-authored-by: Dean Amiel <[email protected]>
Co-authored-by: Kiryl Yermakou <[email protected]>
  • Loading branch information
4 people authored Nov 1, 2023
1 parent 8e5195f commit a1a6598
Show file tree
Hide file tree
Showing 14 changed files with 112 additions and 171 deletions.
15 changes: 1 addition & 14 deletions contracts/interfaces/IInterchainAddressTracker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { IContractIdentifier } from './IContractIdentifier.sol';
* @title IInterchainAddressTracker
* @dev Manages trusted addresses by chain, keeps track of addresses supported by the Axelar gateway contract
*/
interface IInterchainAddressTracker is IContractIdentifier {
interface IInterchainAddressTracker {
error ZeroAddress();
error LengthMismatch();
error ZeroStringLength();
Expand Down Expand Up @@ -43,17 +43,4 @@ interface IInterchainAddressTracker is IContractIdentifier {
* @return bool true if the sender chain/address are trusted, false otherwise
*/
function isTrustedAddress(string calldata chain, string calldata address_) external view returns (bool);

/**
* @dev Sets the trusted address for the specified chain
* @param chain Chain name to be trusted
* @param address_ Trusted address to be added for the chain
*/
function setTrustedAddress(string memory chain, string memory address_) external;

/**
* @dev Remove the trusted address of the chain.
* @param chain Chain name that should be made untrusted
*/
function removeTrustedAddress(string calldata chain) external;
}
25 changes: 23 additions & 2 deletions contracts/test/utils/TestInterchainAddressTracker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,36 @@

pragma solidity ^0.8.0;

import { Ownable } from '../../utils/Ownable.sol';
import { InterchainAddressTracker } from '../../utils/InterchainAddressTracker.sol';

contract TestInterchainAddressTracker is InterchainAddressTracker {
contract TestInterchainAddressTracker is InterchainAddressTracker, Ownable {
string public name = 'Test'; // Dummy var for a different bytecode

error Invalid();

constructor(string memory chainName_) InterchainAddressTracker(chainName_) {
constructor(
string memory chainName_,
string[] memory trustedChainNames,
string[] memory trustedAddresses
) InterchainAddressTracker(chainName_) Ownable(msg.sender) {
if (_CHAIN_NAME_SLOT != bytes32(uint256(keccak256('interchain-address-tracker-chain-name')) - 1))
revert Invalid();

uint256 length = trustedChainNames.length;

if (length != trustedAddresses.length) revert LengthMismatch();

for (uint256 i; i < length; ++i) {
_setTrustedAddress(trustedChainNames[i], trustedAddresses[i]);
}
}

function setTrustedAddress(string memory chain, string memory address_) external onlyOwner {
_setTrustedAddress(chain, address_);
}

function removeTrustedAddress(string memory chain) external onlyOwner {
_removeTrustedAddress(chain);
}
}
15 changes: 0 additions & 15 deletions contracts/test/utils/TestInterchainAddressTrackerProxy.sol

This file was deleted.

4 changes: 4 additions & 0 deletions contracts/test/utils/TestMulticall.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ contract TestMulticall is Multicall {
return nonce_;
}

function function3() external pure {
revert('Mock function revert');
}

function multicallTest(bytes[] calldata data) external {
lastMulticallReturns = multicall(data);
}
Expand Down
4 changes: 4 additions & 0 deletions contracts/test/utils/TestPausable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ contract TestPausable is Pausable {
function testPaused() external whenNotPaused {
emit TestEvent();
}

function testNotPaused() external whenPaused {
emit TestEvent();
}
}
4 changes: 4 additions & 0 deletions contracts/test/utils/TestReentrancyGuard.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,9 @@ contract TestReentrancyGuard is ReentrancyGuard {
value = 2;
}

function testFunction2() external noReEntrancy {
value = 2;
}

function callback() external noReEntrancy {}
}
97 changes: 32 additions & 65 deletions contracts/utils/InterchainAddressTracker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,20 @@ pragma solidity ^0.8.0;

import { IInterchainAddressTracker } from '../interfaces/IInterchainAddressTracker.sol';
import { StringStorage } from '../libs/StringStorage.sol';
import { Upgradable } from '../upgradable/Upgradable.sol';

/**
* @title InterchainAddressTracker
* @dev Manages and validates trusted interchain addresses of an application.
*/
contract InterchainAddressTracker is IInterchainAddressTracker, Upgradable {
contract InterchainAddressTracker is IInterchainAddressTracker {
bytes32 internal constant PREFIX_ADDRESS_MAPPING = keccak256('interchain-address-tracker-address-mapping');
bytes32 internal constant PREFIX_ADDRESS_HASH_MAPPING =
keccak256('interchain-address-tracker-address-hash-mapping');
// bytes32(uint256(keccak256('interchain-address-tracker-chain-name')) - 1)
bytes32 internal constant _CHAIN_NAME_SLOT = 0x0e2c162a1f4b5cff9fdbd6b34678a9bcb9898a0b9fbca695b112d61688d8b2ac;

bytes32 private constant CONTRACT_ID = keccak256('interchain-address-tracker');

/**
* @dev Constructs the InterchainAddressTracker contract, both array parameters must be equal in length.
* @dev Constructs the InterchainAddressTracker contract.
* @param chainName_ The name of the current chain.
*/
constructor(string memory chainName_) {
Expand All @@ -29,67 +26,13 @@ contract InterchainAddressTracker is IInterchainAddressTracker, Upgradable {
StringStorage.set(_CHAIN_NAME_SLOT, chainName_);
}

/**
* @notice Getter for the contract id.
*/
function contractId() external pure returns (bytes32) {
return CONTRACT_ID;
}

function _setup(bytes calldata params) internal override {
(string[] memory trustedChainNames, string[] memory trustedAddresses) = abi.decode(
params,
(string[], string[])
);
uint256 length = trustedChainNames.length;

if (length != trustedAddresses.length) revert LengthMismatch();

for (uint256 i; i < length; ++i) {
setTrustedAddress(trustedChainNames[i], trustedAddresses[i]);
}
}

/**
* @dev Gets the name of the chain this is deployed at
*/
function chainName() external view returns (string memory chainName_) {
chainName_ = StringStorage.get(_CHAIN_NAME_SLOT);
}

/**
* @dev Gets the key for the trusted address at a remote chain
* @param chain Chain name of the remote chain
* @return slot the slot to store the trusted address in
*/
function _getTrustedAddressSlot(string memory chain) internal pure returns (bytes32 slot) {
slot = keccak256(abi.encode(PREFIX_ADDRESS_MAPPING, chain));
}

/**
* @dev Gets the key for the trusted address at a remote chain
* @param chain Chain name of the remote chain
* @return slot the slot to store the trusted address hash in
*/
function _getTrustedAddressHashSlot(string memory chain) internal pure returns (bytes32 slot) {
slot = keccak256(abi.encode(PREFIX_ADDRESS_HASH_MAPPING, chain));
}

/**
* @dev Sets the trusted address and its hash for a remote chain
* @param chain Chain name of the remote chain
* @param trustedAddress_ the string representation of the trusted address
*/
function _setTrustedAddress(string memory chain, string memory trustedAddress_) internal {
StringStorage.set(_getTrustedAddressSlot(chain), trustedAddress_);

bytes32 slot = _getTrustedAddressHashSlot(chain);
bytes32 addressHash = keccak256(bytes(trustedAddress_));
assembly {
sstore(slot, addressHash)
}
}

/**
* @dev Gets the trusted address at a remote chain
* @param chain Chain name of the remote chain
Expand Down Expand Up @@ -124,15 +67,39 @@ contract InterchainAddressTracker is IInterchainAddressTracker, Upgradable {
}

/**
* @dev Sets the trusted address for the specified chain
* @param chain Chain name to be trusted
* @param address_ Trusted address to be added for the chain
* @dev Gets the key for the trusted address at a remote chain
* @param chain Chain name of the remote chain
* @return slot the slot to store the trusted address in
*/
function _getTrustedAddressSlot(string memory chain) internal pure returns (bytes32 slot) {
slot = keccak256(abi.encode(PREFIX_ADDRESS_MAPPING, chain));
}

/**
* @dev Gets the key for the trusted address at a remote chain
* @param chain Chain name of the remote chain
* @return slot the slot to store the trusted address hash in
*/
function _getTrustedAddressHashSlot(string memory chain) internal pure returns (bytes32 slot) {
slot = keccak256(abi.encode(PREFIX_ADDRESS_HASH_MAPPING, chain));
}

/**
* @dev Sets the trusted address and its hash for a remote chain
* @param chain Chain name of the remote chain
* @param address_ the string representation of the trusted address
*/
function setTrustedAddress(string memory chain, string memory address_) public onlyOwner {
function _setTrustedAddress(string memory chain, string memory address_) internal {
if (bytes(chain).length == 0) revert ZeroStringLength();
if (bytes(address_).length == 0) revert ZeroStringLength();

_setTrustedAddress(chain, address_);
StringStorage.set(_getTrustedAddressSlot(chain), address_);

bytes32 slot = _getTrustedAddressHashSlot(chain);
bytes32 addressHash = keccak256(bytes(address_));
assembly {
sstore(slot, addressHash)
}

emit TrustedAddressSet(chain, address_);
}
Expand All @@ -141,7 +108,7 @@ contract InterchainAddressTracker is IInterchainAddressTracker, Upgradable {
* @dev Remove the trusted address of the chain.
* @param chain Chain name that should be made untrusted
*/
function removeTrustedAddress(string calldata chain) external onlyOwner {
function _removeTrustedAddress(string memory chain) internal {
if (bytes(chain).length == 0) revert ZeroStringLength();

StringStorage.clear(_getTrustedAddressSlot(chain));
Expand Down
33 changes: 0 additions & 33 deletions contracts/utils/InterchainAddressTrackerProxy.sol

This file was deleted.

4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@axelar-network/axelar-gmp-sdk-solidity",
"version": "5.6.0",
"version": "5.6.1",
"description": "Solidity GMP SDK and utilities provided by Axelar for cross-chain development",
"main": "index.js",
"scripts": {
Expand Down
42 changes: 3 additions & 39 deletions test/utils/InterchainAddressTracker.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@

const chai = require('chai');
const { ethers } = require('hardhat');
const {
utils: { defaultAbiCoder },
} = ethers;
const { expect } = chai;
const { deployContract } = require('../utils.js');

Expand All @@ -27,34 +24,22 @@ describe('InterchainAddressTracker', () => {
otherWallet = wallets[1];
defaultAddresses.push(wallets[2].address);
defaultAddresses.push('another address format');
const implementation = await deployContract(
ownerWallet,
'InterchainAddressTracker',
[chainName],
);
const params = defaultAbiCoder.encode(
['string[]', 'string[]'],
[defaultChains, defaultAddresses],
);
interchainAddressTracker = await deployContract(
ownerWallet,
'InterchainAddressTrackerProxy',
[implementation.address, ownerWallet.address, params],
'TestInterchainAddressTracker',
[chainName, defaultChains, defaultAddresses],
);

interchainAddressTrackerFactory = await ethers.getContractFactory(
'InterchainAddressTracker',
);
interchainAddressTracker = interchainAddressTrackerFactory
.attach(interchainAddressTracker.address)
.connect(ownerWallet);
});

it('check internal constants', async () => {
const interchainAddressTracker = await deployContract(
ownerWallet,
'TestInterchainAddressTracker',
[chainName],
[chainName, [], []],
);

expect(await interchainAddressTracker.chainName()).to.equal(chainName);
Expand All @@ -69,27 +54,6 @@ describe('InterchainAddressTracker', () => {
);
});

it('Should revert on interchainAddressTracker deployment with length mismatch between chains and trusted addresses arrays', async () => {
const interchainAddressTrackerImpl = await deployContract(
ownerWallet,
'InterchainAddressTracker',
[chainName],
);
const interchainAddressTrackerProxyFactory =
await ethers.getContractFactory('InterchainAddressTrackerProxy');
const params = defaultAbiCoder.encode(
['string[]', 'string[]'],
[['Chain A'], []],
);
await expect(
interchainAddressTrackerProxyFactory.deploy(
interchainAddressTrackerImpl.address,
ownerWallet.address,
params,
),
).to.be.revertedWithCustomError(interchainAddressTracker, 'SetupFailed');
});

it('Should get empty strings for the trusted address for unregistered chains', async () => {
expect(await interchainAddressTracker.trustedAddress(otherChain)).to.equal(
'',
Expand Down
Loading

0 comments on commit a1a6598

Please sign in to comment.