Address Provider
The AddressProvider serves as the entry point contract for Curve's various registries and is deployed on all chains where Curve is operational. The contract holds the most important contract addresses.
The AddressProvider contract is managed by an admin who is currently an individual at Curve, rather than the Curve DAO1. This admin has the ability to update, add or remove new IDs within the contract. When integrating this contract into systems or relying on it for critical components, it is essential to consider that these IDs and their associated addresses can be modified at any time.
Reading IDs
For the full mapping of IDs please see get_id_info.
ID information is stored in a struct, containing an address, a detailed description, its version, and the timestamp marking its most recent modification:
struct AddressInfo:
addr: address
description: String[256]
version: uint256
last_modified: uint256
A Google Colab notebook that provides a full mapping of IDs by iterating over all ids via calling the get_id_info can be found here: Google Colab Notebook
The notebook is compatible with querying IDs for different chains and returns a table as shown below:

ids
AddressProvider.ids() -> DynArray[uint256, 1000]: viewGetter function for all the IDs of active registry items in the AddressProvider.
Returns: active ids (DynArray[uint256, 1000]).
<>Source code▼
_ids: DynArray[uint256, 1000]
@view
@external
def ids() -> DynArray[uint256, 1000]:
"""
@notice returns IDs of active registry items in the AddressProvider.
@returns An array of IDs.
"""
_ids: DynArray[uint256, 1000] = []
for _id in self._ids:
if self.check_id_exists[_id]:
_ids.append(_id)
return _ids
▶Example▼
This method returns all populated IDs.
>>> AddressProvider.ids()
0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 14, 15, 16, 17, 19, 21, 22, 23, 25, 18
get_id_info
AddressProvider.get_id_info(arg0: uint256) -> tuple: viewGetter function to retrieve information about a specific ID.
Returns: AddressInfo struct containing the addr (address), description (String[256]), version (uint256) and last_modified (uint256).
| Input | Type | Description |
|---|---|---|
arg0 | uint256 | ID to get the information for |
<>Source code▼
struct AddressInfo:
addr: address
description: String[256]
version: uint256
last_modified: uint256
get_id_info: public(HashMap[uint256, AddressInfo])
▶Example▼
This method returns the address of the contract, the description, the ID version (which is incremented by 1 each time the ID is updated), and the timestamp of the last modification. When calling the function for an unpopulated ID, it returns an empty AddressInfo struct.
>>> AddressProvider.get_id_info(0)
'0x90E00ACe148ca3b23Ac1bC8C240C2a7Dd9c2d7f5, Stableswap Custom Pool Registry, 1, 1712655599'
>>> AddressProvider.get_id_info(9)
'0x0000000000000000000000000000000000000000, '', 0, 0'
get_address
AddressProvider.get_address(_id: uint256) -> address: viewGetter for the contract address of an ID.
Returns: contract (address).
| Input | Type | Description |
|---|---|---|
_id | uint256 | ID to get the contract address for |
<>Source code▼
struct AddressInfo:
addr: address
description: String[256]
version: uint256
last_modified: uint256
get_id_info: public(HashMap[uint256, AddressInfo])
@view
@external
def get_address(_id: uint256) -> address:
"""
@notice Fetch the address associated with `_id`
@dev Returns empty(address) if `_id` has not been defined, or has been unset
@param _id Identifier to fetch an address for
@return Current address associated to `_id`
"""
return self.get_id_info[_id].addr
▶Example▼
This method returns the address of an ID.
>>> AddressProvider.get_address(0)
'0x90E00ACe148ca3b23Ac1bC8C240C2a7Dd9c2d7f5'
check_id_exists
AddressProvider.check_id_exists(arg0: uint256) -> bool: viewFunction to check if an ID exists.
Returns: true or false (bool).
| Input | Type | Description |
|---|---|---|
arg0 | uint256 | ID to check |
<>Source code▼
check_id_exists: public(HashMap[uint256, bool])
▶Example▼
This method checks if a certain ID exists.
>>> AddressProvider.check_id_exists(0)
'true'
>>> AddressProvider.check_id_exists(9)
'false'
num_entries
AddressProvider.num_entries() -> uint256: viewGetter for the number of entries. The count increments by one upon calling _add_new_id and decreases by one upon calling _remove_id.
Returns: number of entries (uint256).
<>Source code▼
num_entries: public(uint256)
▶Example▼
This method returns the total number of IDs added to the AddressProvider.
>>> AddressProvider.num_entries()
20
Adding, Removing and Updating IDs
IDs can be added, removed, or adjusted by the admin of the contract.
The AddressProvider contract is managed by an admin who is currently an individual at Curve, rather than the Curve DAO1. This admin has the ability to update, add or remove new IDs within the contract. When integrating this contract into systems or relying on it for critical components, it is essential to consider that these IDs and their associated addresses can be modified at any time.
update_id
AddressProvider.update_id(_id: uint256, _new_address: address, _new_description: String[64])This function can only be called by the admin of the contract.
Function to update the address and description of an ID.
Emits: EntryModified
| Input | Type | Description |
|---|---|---|
_id | uint256 | ID to update |
_new_address | address | New address |
_new_description | String[64] | New description |
<>Source code▼
event EntryModified:
id: indexed(uint256)
version: uint256
@external
def update_id(
_id: uint256,
_new_address: address,
_new_description: String[64],
):
"""
@notice Update entries at an ID
@param _id Address assigned to the input _id
@param _new_address Address assigned to the _id
@param _new_description Human-readable description of the identifier
"""
assert msg.sender == self.admin # dev: admin-only function
assert self.check_id_exists[_id] # dev: id does not exist
# Update entry at _id:
self.get_id_info[_id].addr = _new_address
self.get_id_info[_id].description = _new_description
# Update metadata (version, update time):
self._update_entry_metadata(_id)
@internal
def _update_entry_metadata(_id: uint256):
version: uint256 = self.get_id_info[_id].version + 1
self.get_id_info[_id].version = version
self.get_id_info[_id].last_modified = block.timestamp
log EntryModified(_id, version)
▶Example▼
This function updates the ID at index 0.
>>> AddressProvider.update_id(0, "0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E", "crvUSD Token")
update_address
AddressProvider.update_address(_id: uint256, _address: address)This function can only be called by the admin of the contract.
Function to update the address of an ID.
Emits: EntryModified
| Input | Type | Description |
|---|---|---|
_id | uint256 | ID to change the address for |
_address | address | New address to change it to |
<>Source code▼
event EntryModified:
id: indexed(uint256)
version: uint256
check_id_exists: public(HashMap[uint256, bool])
get_id_info: public(HashMap[uint256, AddressInfo])
@external
def update_address(_id: uint256, _address: address):
"""
@notice Set a new address for an existing identifier
@param _id Identifier to set the new address for
@param _address Address to set
"""
assert msg.sender == self.admin # dev: admin-only function
assert self.check_id_exists[_id] # dev: id does not exist
# Update address:
self.get_id_info[_id].addr = _address
# Update metadata (version, update time):
self._update_entry_metadata(_id)
@internal
def _update_entry_metadata(_id: uint256):
version: uint256 = self.get_id_info[_id].version + 1
self.get_id_info[_id].version = version
self.get_id_info[_id].last_modified = block.timestamp
log EntryModified(_id, version)
▶Example▼
This example changes the address for ID 0.
>>> AddressProvider.update_address(0, "0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E")
update_description
AddressProvider.update_description(_id: uint256, _description: String[256])This function can only be called by the admin of the contract.
Function to update the description of an ID.
Emits: EntryModified
| Input | Type | Description |
|---|---|---|
_id | uint256 | ID to change the description for |
_description | String[256] | New description |
<>Source code▼
event EntryModified:
id: indexed(uint256)
version: uint256
check_id_exists: public(HashMap[uint256, bool])
get_id_info: public(HashMap[uint256, AddressInfo])
@external
def update_description(_id: uint256, _description: String[256]):
"""
@notice Update description for an existing _id
@param _id Identifier to set the new description for
@param _description New description to set
"""
assert msg.sender == self.admin # dev: admin-only function
assert self.check_id_exists[_id] # dev: id does not exist
# Update description:
self.get_id_info[_id].description = _description
# Update metadata (version, update time):
self._update_entry_metadata(_id)
@internal
def _update_entry_metadata(_id: uint256):
version: uint256 = self.get_id_info[_id].version + 1
self.get_id_info[_id].version = version
self.get_id_info[_id].last_modified = block.timestamp
log EntryModified(_id, version)
add_new_id
AddressProvider.add_new_id(_id: uint256, _address: address, _description: String[64])This function can only be called by the admin of the contract.
Function to add a new registry item to the AddressProvider.
Emits: NewEntry
| Input | Type | Description |
|---|---|---|
_id | uint256 | ID to add; Reverts if ID number is already used |
_address | address | New address |
_description | String[64] | New description |
<>Source code▼
event NewEntry:
id: indexed(uint256)
addr: address
description: String[64]
@external
def add_new_id(
_id: uint256,
_address: address,
_description: String[64],
):
"""
@notice Enter a new registry item
@param _id ID assigned to the address
@param _address Address assigned to the ID
@param _description Human-readable description of the ID
"""
assert msg.sender == self.admin # dev: admin-only function
self._add_new_id(_id, _address, _description)
@internal
def _add_new_id(
_id: uint256,
_address: address,
_description: String[64]
):
assert not self.check_id_exists[_id] # dev: id exists
self.check_id_exists[_id] = True
self._ids.append(_id)
# Add entry:
self.get_id_info[_id] = AddressInfo(
{
addr: _address,
description: _description,
version: 1,
last_modified: block.timestamp,
}
)
self.num_entries += 1
log NewEntry(_id, _address, _description)
add_new_ids
AddressProvider.add_new_ids(_ids: DynArray[uint256, 25], _addresses: DynArray[address, 25], _descriptions: DynArray[String[64], 25])This function can only be called by the admin of the contract.
Function to add multiple new registry items to the AddressProvider at once.
Emits: NewEntry
| Input | Type | Description |
|---|---|---|
_ids | DynArray[uint256, 25] | IDs to add; Reverts if ID number is already used |
_addresses | DynArray[address, 25] | ID addresses |
_descriptions | DynArray[String[64], 25] | ID descriptions |
<>Source code▼
event NewEntry:
id: indexed(uint256)
addr: address
description: String[64]
@external
def add_new_ids(
_ids: DynArray[uint256, 25],
_addresses: DynArray[address, 25],
_descriptions: DynArray[String[64], 25],
):
"""
@notice Enter new registry items
@param _ids IDs assigned to addresses
@param _addresses Addresses assigned to corresponding IDs
@param _descriptions Human-readable description of each of the IDs
"""
assert msg.sender == self.admin # dev: admin-only function
# Check lengths
assert len(_ids) == len(_addresses)
assert len(_addresses) == len(_descriptions)
for i in range(len(_ids), bound=20):
self._add_new_id(
_ids[i],
_addresses[i],
_descriptions[i]
)
@internal
def _add_new_id(
_id: uint256,
_address: address,
_description: String[64]
):
assert not self.check_id_exists[_id] # dev: id exists
self.check_id_exists[_id] = True
self._ids.append(_id)
# Add entry:
self.get_id_info[_id] = AddressInfo(
{
addr: _address,
description: _description,
version: 1,
last_modified: block.timestamp,
}
)
self.num_entries += 1
log NewEntry(_id, _address, _description)
remove_id
AddressProvider.remove_id(_id: uint256) -> boolThis function can only be called by the admin of the contract.
Function to remove a registry item from the AddressProvider.
Returns: true (bool).
Emits: EntryRemoved
| Input | Type | Description |
|---|---|---|
_id | uint256 | ID to remove |
<>Source code▼
event EntryRemoved:
id: indexed(uint256)
@external
def remove_id(_id: uint256) -> bool:
"""
@notice Unset an existing identifier
@param _id Identifier to unset
@return bool success
"""
assert msg.sender == self.admin # dev: admin-only function
return self._remove_id(_id)
@internal
def _remove_id(_id: uint256) -> bool:
assert self.check_id_exists[_id] # dev: id does not exist
# Clear ID:
self.get_id_info[_id].addr = empty(address)
self.get_id_info[_id].last_modified = 0
self.get_id_info[_id].description = ''
self.get_id_info[_id].version = 0
self.check_id_exists[_id] = False
# Reduce num entries:
self.num_entries -= 1
# Emit 0 in version to notify removal of id:
log EntryRemoved(_id)
return True
remove_ids
AddressProvider.remove_ids(_ids: DynArray[uint256, 20]) -> boolThis function can only be called by the admin of the contract.
Function to remove multiple registry items from the AddressProvider at once.
Returns: true (bool).
Emits: EntryRemoved
| Input | Type | Description |
|---|---|---|
_ids | DynArray[uint256, 20] | IDs to remove |
<>Source code▼
event EntryRemoved:
id: indexed(uint256)
@external
def remove_ids(_ids: DynArray[uint256, 20]) -> bool:
"""
@notice Unset existing identifiers
@param _id DynArray of identifier to unset
@return bool success
"""
assert msg.sender == self.admin # dev: admin-only function
for _id in _ids:
assert self._remove_id(_id)
return True
@internal
def _remove_id(_id: uint256) -> bool:
assert self.check_id_exists[_id] # dev: id does not exist
# Clear ID:
self.get_id_info[_id].addr = empty(address)
self.get_id_info[_id].last_modified = 0
self.get_id_info[_id].description = ''
self.get_id_info[_id].version = 0
self.check_id_exists[_id] = False
# Reduce num entries:
self.num_entries -= 1
# Emit 0 in version to notify removal of id:
log EntryRemoved(_id)
return True
Contract Ownership
The ownership of the contract follows the classic two-step ownership model used across most Curve contracts.
admin
AddressProvider.admin() -> address: viewGetter for the admin of the contract. This address can add, remove or update ID's.
Returns: admin (address).
<>Source code▼
admin: public(address)
@external
def __init__():
self.admin = tx.origin
▶Example▼
>>> AddressProvider.admin()
'0x2d12D0907A388811e3AA855A550F959501d303EE'
future_admin
AddressProvider.future_admin() -> address: viewGetter for the future admin of the contract.
Returns: future admin (address).
<>Source code▼
future_admin: public(address)
▶Example▼
>>> AddressProvider.future_admin()
'0x0000000000000000000000000000000000000000'
commit_transfer_ownership
AddressProvider.commit_transfer_ownership(_new_admin: address) -> boolThis function can only be called by the admin of the contract.
Function to initiate a transfer of contract ownership.
Returns: true (bool).
Emits: CommitNewAdmin
| Input | Type | Description |
|---|---|---|
_new_admin | address | Address to transfer the ownership to |
<>Source code▼
event CommitNewAdmin:
admin: indexed(address)
future_admin: public(address)
@external
def commit_transfer_ownership(_new_admin: address) -> bool:
"""
@notice Initiate a transfer of contract ownership
@dev Once initiated, the actual transfer may be performed three days later
@param _new_admin Address of the new owner account
@return bool success
"""
assert msg.sender == self.admin # dev: admin-only function
self.future_admin = _new_admin
log CommitNewAdmin(_new_admin)
return True
apply_transfer_ownership
AddressProvider.apply_transfer_ownership() -> boolThis function can only be called by the future_admin of the contract.
Function to finalize a transfer of contract ownership.
Returns: true (bool).
Emits: NewAdmin
<>Source code▼
event NewAdmin:
admin: indexed(address)
admin: public(address)
future_admin: public(address)
@external
def apply_transfer_ownership() -> bool:
"""
@notice Finalize a transfer of contract ownership
@dev May only be called by the next owner
@return bool success
"""
assert msg.sender == self.future_admin # dev: admin-only function
new_admin: address = self.future_admin
self.admin = new_admin
log NewAdmin(new_admin)
return True
revert_transfer_ownership
AddressProvider.revert_transfer_ownership() -> boolThis function can only be called by the admin of the contract.
Function to revert the transfer of contract ownership.
Returns: true (bool).
<>Source code▼
admin: public(address)
future_admin: public(address)
@external
def revert_transfer_ownership() -> bool:
"""
@notice Revert a transfer of contract ownership
@dev May only be called by the current owner
@return bool success
"""
assert msg.sender == self.admin # dev: admin-only function
self.future_admin = empty(address)
return True