Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/comment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ permissions:

jobs:
comment:
uses: bgd-labs/github-workflows/.github/workflows/comment.yml@main
uses: aave-dao/github-workflows/.github/workflows/comment.yml@main
secrets:
READ_ONLY_PAT: ${{ secrets.READ_ONLY_PAT }}
8 changes: 4 additions & 4 deletions .github/workflows/tests-merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
jobs:
lint:
name: Prettier lint check
uses: bgd-labs/github-workflows/.github/workflows/foundry-lint-prettier.yml@main
uses: aave-dao/github-workflows/.github/workflows/foundry-lint-prettier.yml@main
test:
name: Foundry build n test
runs-on: ubuntu-latest
Expand All @@ -20,15 +20,15 @@ jobs:
token: ${{ secrets.READ_ONLY_PAT || github.token }}

- name: Run Foundry setup
uses: bgd-labs/github-workflows/.github/actions/foundry-setup@main
uses: aave-dao/github-workflows/.github/actions/foundry-setup@main
with:
FOUNDRY_VERSION: stable

- name: Run Forge size
uses: bgd-labs/github-workflows/.github/actions/foundry-size@main
uses: aave-dao/github-workflows/.github/actions/foundry-size@main

- name: Run Forge tests
id: test
uses: bgd-labs/github-workflows/.github/actions/foundry-test@main
uses: aave-dao/github-workflows/.github/actions/foundry-test@main
with:
FOUNDRY_PROFILE: ci
12 changes: 6 additions & 6 deletions .github/workflows/tests-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
jobs:
lint:
name: Prettier lint check
uses: bgd-labs/github-workflows/.github/workflows/foundry-lint-prettier.yml@main
uses: aave-dao/github-workflows/.github/workflows/foundry-lint-prettier.yml@main
test:
name: Foundry build n test
runs-on: ubuntu-latest
Expand All @@ -17,23 +17,23 @@ jobs:
token: ${{ secrets.READ_ONLY_PAT || github.token }}

- name: Run Foundry setup
uses: bgd-labs/github-workflows/.github/actions/foundry-setup@main
uses: aave-dao/github-workflows/.github/actions/foundry-setup@main
with:
FOUNDRY_VERSION: stable

- name: Run Forge size
uses: bgd-labs/github-workflows/.github/actions/foundry-size@main
uses: aave-dao/github-workflows/.github/actions/foundry-size@main

- name: Run Gas report
uses: bgd-labs/github-workflows/.github/actions/foundry-gas-report@main
uses: aave-dao/github-workflows/.github/actions/foundry-gas-report@main

- name: Run Forge tests
uses: bgd-labs/github-workflows/.github/actions/foundry-test@main
uses: aave-dao/github-workflows/.github/actions/foundry-test@main
with:
FOUNDRY_PROFILE: pr
FORGE_SNAPSHOT_CHECK: true

- name: Upload & Trigger Comment artifact
uses: bgd-labs/github-workflows/.github/actions/comment-artifact@main
uses: aave-dao/github-workflows/.github/actions/comment-artifact@main
with:
nameSuffix: "default"
166 changes: 166 additions & 0 deletions src/addresses-provider/V4AddressesProvider.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// SPDX-License-Identifier: LicenseRef-BUSL
pragma solidity 0.8.28;

import {Ownable2StepUpgradeable} from 'src/dependencies/openzeppelin-upgradeable/Ownable2StepUpgradeable.sol';
import {EnumerableSet} from 'src/dependencies/openzeppelin/EnumerableSet.sol';
import {V4AddressesProviderStorage} from 'src/addresses-provider/V4AddressesProviderStorage.sol';
import {IV4AddressesProvider} from 'src/addresses-provider/interfaces/IV4AddressesProvider.sol';

/// @title V4AddressesProvider
/// @author Aave Labs
/// @notice Main registry of Aave V4 contract addresses.
abstract contract V4AddressesProvider is

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thinking more its a registry

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I followed the v3 naming convention here (also with the plural in "addresses" which I don't like). I'm fine changing the name, thoughts @Kogaroshi @miguelmtzinf ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's better to keep v3 name convention, so we don't have more difference of naming in the tooling.

V4AddressesProviderStorage,
Ownable2StepUpgradeable,
IV4AddressesProvider
{
using EnumerableSet for *;

/// @inheritdoc IV4AddressesProvider
string public constant CANONICAL_HUB_TAG = 'CANONICAL_HUB';

/// @inheritdoc IV4AddressesProvider
string public constant CANONICAL_SPOKE_TAG = 'CANONICAL_SPOKE';

/// @inheritdoc IV4AddressesProvider
string public constant TOKENIZATION_SPOKE_TAG = 'TOKENIZATION_SPOKE';

/// @inheritdoc IV4AddressesProvider
string public constant TREASURY_SPOKE_TAG = 'TREASURY_SPOKE';

/// @dev To be overridden by the inheriting V4AddressesProvider instance contract.
function initialize(address owner) external virtual;

/// @inheritdoc IV4AddressesProvider
function setAddress(
string memory name,
string memory tag,
address newAddress
) external onlyOwner {
_setAddress({name: name, tag: tag, newAddress: newAddress});
}

/// @inheritdoc IV4AddressesProvider
function setCanonicalHub(string memory name, address hub) external onlyOwner {
_setAddress({name: name, tag: CANONICAL_HUB_TAG, newAddress: hub});
}

/// @inheritdoc IV4AddressesProvider
function setCanonicalSpoke(string memory name, address spoke) external onlyOwner {
_setAddress({name: name, tag: CANONICAL_SPOKE_TAG, newAddress: spoke});
}

/// @inheritdoc IV4AddressesProvider
function setTokenizationSpoke(string memory name, address spoke) external onlyOwner {
_setAddress({name: name, tag: TOKENIZATION_SPOKE_TAG, newAddress: spoke});
}

/// @inheritdoc IV4AddressesProvider
function setTreasurySpoke(string memory name, address spoke) external onlyOwner {
_setAddress({name: name, tag: TREASURY_SPOKE_TAG, newAddress: spoke});
}

/// @inheritdoc IV4AddressesProvider
function getAddressEntry(bytes32 id) external view returns (AddressEntry memory) {
return _addressEntries[id];
}

/// @inheritdoc IV4AddressesProvider
function getIds(string memory tag) external view returns (bytes32[] memory) {
return _taggedIds[tag].values();
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

annoyingly we might need to overload with index and length methods instead of this bc we'll get a finding says array size can make inflate over gas limit (unlikely), we've done this way already elsewhere with array getters in the codebase

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes true, we should do this

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


/// @inheritdoc IV4AddressesProvider
function getTags() external view returns (string[] memory) {
return _tags.values();
}

/// @inheritdoc IV4AddressesProvider
function getCanonicalHub(string memory name) external view returns (address) {
Comment thread
DhairyaSethi marked this conversation as resolved.
Outdated
return getAddress({name: name, tag: CANONICAL_HUB_TAG});
}

/// @inheritdoc IV4AddressesProvider
function getCanonicalHubs() external view returns (address[] memory) {
return getAddresses(CANONICAL_HUB_TAG);
}

/// @inheritdoc IV4AddressesProvider
function getCanonicalSpoke(string memory name) external view returns (address) {
return getAddress({name: name, tag: CANONICAL_SPOKE_TAG});
}

/// @inheritdoc IV4AddressesProvider
function getCanonicalSpokes() external view returns (address[] memory) {
return getAddresses(CANONICAL_SPOKE_TAG);
}

/// @inheritdoc IV4AddressesProvider
function getTokenizationSpoke(string memory name) external view returns (address) {
return getAddress({name: name, tag: TOKENIZATION_SPOKE_TAG});
}

/// @inheritdoc IV4AddressesProvider
function getTokenizationSpokes() external view returns (address[] memory) {
return getAddresses(TOKENIZATION_SPOKE_TAG);
}

/// @inheritdoc IV4AddressesProvider
function getTreasurySpoke(string memory name) external view returns (address) {
return getAddress({name: name, tag: TREASURY_SPOKE_TAG});
}

/// @inheritdoc IV4AddressesProvider
function getTreasurySpokes() external view returns (address[] memory) {
return getAddresses(TREASURY_SPOKE_TAG);
}

/// @inheritdoc IV4AddressesProvider
function getAddress(bytes32 id) public view returns (address) {
return _addressEntries[id].addr;
}

/// @inheritdoc IV4AddressesProvider
function getAddress(string memory name, string memory tag) public view returns (address) {
return getAddress(getId({name: name, tag: tag}));
}

/// @inheritdoc IV4AddressesProvider
function getAddresses(string memory tag) public view returns (address[] memory) {
bytes32[] memory ids = _taggedIds[tag].values();
address[] memory addresses = new address[](ids.length);
for (uint256 i = 0; i < ids.length; i++) {
addresses[i] = _addressEntries[ids[i]].addr;
}
return addresses;
}

/// @inheritdoc IV4AddressesProvider
function getId(string memory name, string memory tag) public pure returns (bytes32) {
return keccak256(bytes(string.concat(name, '_', tag)));
}

function _setAddress(string memory name, string memory tag, address newAddress) internal {
require(bytes(name).length > 0, InvalidName());
require(bytes(tag).length > 0, InvalidTag());

bytes32 id = getId({name: name, tag: tag});
AddressEntry memory oldEntry = _addressEntries[id];

if (newAddress == address(0)) {
require(oldEntry.addr != address(0), AddressNotSet(id));
_taggedIds[oldEntry.tag].remove(id);
if (_taggedIds[oldEntry.tag].length() == 0) {
_tags.remove(oldEntry.tag);
}
delete _addressEntries[id];
} else {
require(oldEntry.addr == address(0), AddressAlreadySet(id));
_addressEntries[id] = AddressEntry({addr: newAddress, tag: tag});
_taggedIds[tag].add(id);
_tags.add(tag);
}

emit AddressSet(id, name, tag, oldEntry.addr, newAddress);
}
}
23 changes: 23 additions & 0 deletions src/addresses-provider/V4AddressesProviderStorage.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: LicenseRef-BUSL
pragma solidity 0.8.28;

import {EnumerableSet} from 'src/dependencies/openzeppelin/EnumerableSet.sol';
import {IV4AddressesProvider} from 'src/addresses-provider/interfaces/IV4AddressesProvider.sol';

/// @title V4AddressesProviderStorage
/// @author Aave Labs
/// @notice Storage layout for the V4AddressesProvider contract.
/// @dev This contract defines all storage variables used by the V4AddressesProvider.
abstract contract V4AddressesProviderStorage {
/// @dev Map of entry identifiers to address entries.
mapping(bytes32 id => IV4AddressesProvider.AddressEntry) internal _addressEntries;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i d follow the same conventions we used as for AccessManagerEnumerable.
It's a bit unclear what each var is for (without looking at the definition/docs)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


/// @dev Map of tags to set of entry identifiers.
mapping(string tag => EnumerableSet.Bytes32Set ids) internal _taggedIds;

/// @dev Set of all tags with at least one registered entry.
EnumerableSet.StringSet internal _tags;

/// @dev Reserved storage space to allow for future layout updates.
uint256[50] private __gap;
}
23 changes: 23 additions & 0 deletions src/addresses-provider/instances/V4AddressesProviderInstance.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: LicenseRef-BUSL
pragma solidity 0.8.28;

import {V4AddressesProvider} from 'src/addresses-provider/V4AddressesProvider.sol';

/// @title V4AddressesProviderInstance
/// @author Aave Labs
/// @notice Implementation contract for the V4AddressesProvider.
contract V4AddressesProviderInstance is V4AddressesProvider {
uint64 public constant ADDRESSES_PROVIDER_REVISION = 1;

/// @dev Constructor.
constructor() {
_disableInitializers();
}

/// @notice Initializer.
/// @param owner The address of the owner.
function initialize(address owner) external override reinitializer(ADDRESSES_PROVIDER_REVISION) {
__Ownable_init(owner);
__Ownable2Step_init();
}
}
Loading
Loading