-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: added Interchain Router (#105)
* Added the eternal storage here as well and using it for the InterchainRouter. * Removed Eternal Storage * Added a few tests * Simplified storage and added more tests * made lint happy. * Fixed a warnong * addressed some comments * made slither happy * Added string storage library and a test file to make slither happy. * fix testInterchainRouterProxy * Added delete in string storage, using it in the interchain router and added tests * Rename interchain router to interchain address tracker * changed names of StringStorage functions * refactor names * address comments * bump npm version * addressed comments --------- Co-authored-by: Milap Sheth <[email protected]>
- Loading branch information
1 parent
6160466
commit b64ba1c
Showing
11 changed files
with
555 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
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 { | ||
error ZeroAddress(); | ||
error LengthMismatch(); | ||
error ZeroStringLength(); | ||
error UntrustedChain(); | ||
|
||
event TrustedAddressSet(string chain, string address_); | ||
event TrustedAddressRemoved(string chain); | ||
|
||
/** | ||
* @dev Gets the name of the chain this is deployed at | ||
*/ | ||
function chainName() external view returns (string memory); | ||
|
||
/** | ||
* @dev Gets the trusted address at a remote chain | ||
* @param chain Chain name of the remote chain | ||
* @return trustedAddress_ The trusted address for the chain. Returns '' if the chain is untrusted | ||
*/ | ||
function trustedAddress(string memory chain) external view returns (string memory trustedAddress_); | ||
|
||
/** | ||
* @dev Gets the trusted address hash for a chain | ||
* @param chain Chain name | ||
* @return trustedAddressHash_ the hash of the trusted address for that chain | ||
*/ | ||
function trustedAddressHash(string memory chain) external view returns (bytes32 trustedAddressHash_); | ||
|
||
/** | ||
* @dev Checks whether the interchain sender is a trusted address | ||
* @param chain Chain name of the sender | ||
* @param address_ Address of the sender | ||
* @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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
library StringStorage { | ||
struct Wrapper { | ||
string value; | ||
} | ||
|
||
function set(bytes32 slot, string memory value) internal { | ||
_getStorageStruct(slot).value = value; | ||
} | ||
|
||
function get(bytes32 slot) internal view returns (string memory value) { | ||
value = _getStorageStruct(slot).value; | ||
} | ||
|
||
function clear(bytes32 slot) internal { | ||
delete _getStorageStruct(slot).value; | ||
} | ||
|
||
function _getStorageStruct(bytes32 slot) internal pure returns (Wrapper storage wrapper) { | ||
assembly { | ||
wrapper.slot := slot | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
import { StringStorage } from '../../libs/StringStorage.sol'; | ||
|
||
contract TestStringStorage { | ||
function set(bytes32 slot, string calldata value) external { | ||
StringStorage.set(slot, value); | ||
} | ||
|
||
function get(bytes32 slot) external view returns (string memory value) { | ||
value = StringStorage.get(slot); | ||
} | ||
|
||
function clear(bytes32 slot) external { | ||
StringStorage.clear(slot); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
import { InterchainAddressTracker } from '../../utils/InterchainAddressTracker.sol'; | ||
|
||
contract TestInterchainAddressTracker is InterchainAddressTracker { | ||
string public name = 'Test'; // Dummy var for a different bytecode | ||
|
||
error Invalid(); | ||
|
||
constructor(string memory chainName_) InterchainAddressTracker(chainName_) { | ||
if (_CHAIN_NAME_SLOT != bytes32(uint256(keccak256('interchain-address-tracker-chain-name')) - 1)) | ||
revert Invalid(); | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
contracts/test/utils/TestInterchainAddressTrackerProxy.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
import { InterchainAddressTrackerProxy } from '../../utils/InterchainAddressTrackerProxy.sol'; | ||
|
||
contract TestInterchainAddressTrackerProxy is InterchainAddressTrackerProxy { | ||
constructor( | ||
address implementationAddress, | ||
address owner, | ||
bytes memory params | ||
) InterchainAddressTrackerProxy(implementationAddress, owner, params) { | ||
contractId(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
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 { | ||
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. | ||
* @param chainName_ The name of the current chain. | ||
*/ | ||
constructor(string memory chainName_) { | ||
if (bytes(chainName_).length == 0) revert ZeroStringLength(); | ||
|
||
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 | ||
* @return trustedAddress_ The trusted address for the chain. Returns '' if the chain is untrusted | ||
*/ | ||
function trustedAddress(string memory chain) public view returns (string memory trustedAddress_) { | ||
trustedAddress_ = StringStorage.get(_getTrustedAddressSlot(chain)); | ||
} | ||
|
||
/** | ||
* @dev Gets the trusted address hash for a chain | ||
* @param chain Chain name | ||
* @return trustedAddressHash_ the hash of the trusted address for that chain | ||
*/ | ||
function trustedAddressHash(string memory chain) public view returns (bytes32 trustedAddressHash_) { | ||
bytes32 slot = _getTrustedAddressHashSlot(chain); | ||
assembly { | ||
trustedAddressHash_ := sload(slot) | ||
} | ||
} | ||
|
||
/** | ||
* @dev Checks whether the interchain sender is a trusted address | ||
* @param chain Chain name of the sender | ||
* @param address_ Address of the sender | ||
* @return bool true if the sender chain/address are trusted, false otherwise | ||
*/ | ||
function isTrustedAddress(string calldata chain, string calldata address_) external view returns (bool) { | ||
bytes32 addressHash = keccak256(bytes(address_)); | ||
|
||
return addressHash == trustedAddressHash(chain); | ||
} | ||
|
||
/** | ||
* @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_) public onlyOwner { | ||
if (bytes(chain).length == 0) revert ZeroStringLength(); | ||
if (bytes(address_).length == 0) revert ZeroStringLength(); | ||
|
||
_setTrustedAddress(chain, address_); | ||
|
||
emit TrustedAddressSet(chain, address_); | ||
} | ||
|
||
/** | ||
* @dev Remove the trusted address of the chain. | ||
* @param chain Chain name that should be made untrusted | ||
*/ | ||
function removeTrustedAddress(string calldata chain) external onlyOwner { | ||
if (bytes(chain).length == 0) revert ZeroStringLength(); | ||
|
||
StringStorage.clear(_getTrustedAddressSlot(chain)); | ||
|
||
bytes32 slot = _getTrustedAddressHashSlot(chain); | ||
assembly { | ||
sstore(slot, 0) | ||
} | ||
|
||
emit TrustedAddressRemoved(chain); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
import { Proxy } from '../upgradable/Proxy.sol'; | ||
|
||
/** | ||
* @title InterchainAddressTrackerProxy | ||
* @dev Proxy contract for the InterchainAddressTracker contract. Inherits from the Proxy contract. | ||
*/ | ||
contract InterchainAddressTrackerProxy is Proxy { | ||
bytes32 private constant CONTRACT_ID = keccak256('interchain-address-tracker'); | ||
|
||
/** | ||
* @dev Constructs the InterchainAddressTrackerProxy contract. | ||
* @param implementationAddress Address of the InterchainAddressTracker implementation | ||
* @param owner Address of the owner of the proxy | ||
* @param params The params to be passed to the _setup function of the implementation. | ||
*/ | ||
constructor( | ||
address implementationAddress, | ||
address owner, | ||
bytes memory params | ||
) Proxy(implementationAddress, owner, params) {} | ||
|
||
/** | ||
* @dev Override for the `contractId` function in Proxy. Returns a unique identifier for this contract. | ||
* @return bytes32 Identifier for this contract. | ||
*/ | ||
function contractId() internal pure override returns (bytes32) { | ||
return CONTRACT_ID; | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.